package com.iplant.aps.serviceimpl;

import com.alibaba.fastjson.JSON;
import com.iplant.aps.service.APSService;
import com.iplant.aps.service.mesenum.*;
import com.iplant.aps.service.po.APIResult;
import com.iplant.aps.service.po.OutResult;
import com.iplant.aps.service.po.Pagination;
import com.iplant.aps.service.po.ServiceResult;
import com.iplant.aps.service.po.andon.AndonTime;
import com.iplant.aps.service.po.aps.*;
import com.iplant.aps.service.po.bfc.BFCAuditAction;
import com.iplant.aps.service.po.bfc.BFCMessage;
import com.iplant.aps.service.po.bms.*;
import com.iplant.aps.service.po.bpm.BPMActivitiHisTask;
import com.iplant.aps.service.po.bpm.BPMTaskBase;
import com.iplant.aps.service.po.cfg.CFGCalendar;
import com.iplant.aps.service.po.excel.ExcelData;
import com.iplant.aps.service.po.excel.ExcelLineData;
import com.iplant.aps.service.po.excel.ExcelSheetData;
import com.iplant.aps.service.po.excel.MyExcelSheet;
import com.iplant.aps.service.po.fmc.FMCLine;
import com.iplant.aps.service.po.fmc.FMCTimeZone;
import com.iplant.aps.service.po.fmc.FMCWorkCharge;
import com.iplant.aps.service.po.fmc.FMCWorkspace;
import com.iplant.aps.service.po.fpc.*;
import com.iplant.aps.service.po.ipt.IPTValue;
import com.iplant.aps.service.po.lfs.LFSStoreHouse;
import com.iplant.aps.service.po.lfs.LFSWorkAreaChecker;
import com.iplant.aps.service.po.lfs.LFSWorkAreaStation;
import com.iplant.aps.service.po.mcs.MCSLogInfo;
import com.iplant.aps.service.po.mrp.MRPMaterialPlan;
import com.iplant.aps.service.po.mss.MSSBOM;
import com.iplant.aps.service.po.mss.MSSBOMItem;
import com.iplant.aps.service.po.mss.MSSMaterial;
import com.iplant.aps.service.po.mtc.MTCSectionInfo;
import com.iplant.aps.service.po.ncr.NCRTask;
import com.iplant.aps.service.po.oms.OMSOrder;
import com.iplant.aps.service.po.oms.OMSOrderLessQuestionItem;
import com.iplant.aps.service.po.oms.OMSOutsourceOrder;
import com.iplant.aps.service.po.rsm.RSMTurnOrderTask;
import com.iplant.aps.service.po.sap.*;
import com.iplant.aps.service.po.sch.SCHSecondmentApply;
import com.iplant.aps.service.po.sfc.*;
import com.iplant.aps.service.po.tcm.TCMMaterialChangeItems;
import com.iplant.aps.service.po.tcm.TCMMaterialChangeLog;
import com.iplant.aps.service.po.wms.*;
import com.iplant.aps.service.utils.*;
import com.iplant.aps.serviceimpl.dao.BaseDAO;
import com.iplant.aps.serviceimpl.dao.andon.AndonDAO;
import com.iplant.aps.serviceimpl.dao.aps.*;
import com.iplant.aps.serviceimpl.dao.bfc.BFCMessageDAO;
import com.iplant.aps.serviceimpl.dao.bms.BMSWorkChargeItemDAO;
import com.iplant.aps.serviceimpl.dao.fpc.FPCRouteDAO;
import com.iplant.aps.serviceimpl.dao.mcs.MCSLogInfoDAO;
import com.iplant.aps.serviceimpl.dao.mes.MESSystemConfigDAO;
import com.iplant.aps.serviceimpl.dao.mrp.MRPMaterialPlanDAO;
import com.iplant.aps.serviceimpl.dao.mss.MSSBOMItemDAO;
import com.iplant.aps.serviceimpl.dao.oms.OMSOrderDAO;
import com.iplant.aps.serviceimpl.dao.sch.SCHSecondmentApplyDAO;
import com.iplant.aps.serviceimpl.dao.sfc.*;
import com.iplant.aps.serviceimpl.dao.tcm.TCMMaterialChangeLogDAO;
import com.iplant.aps.serviceimpl.dao.wms.MESMaterialReturnDAO;
import com.iplant.aps.serviceimpl.dao.wms.MESMaterialReturnItemDAO;
import com.iplant.aps.serviceimpl.dao.wms.WMSPickDemandDAO;
import com.iplant.aps.serviceimpl.dao.wms.WMSPickDemandItemDAO;
import com.iplant.aps.serviceimpl.utils.MESServer;
import com.iplant.aps.serviceimpl.utils.aps.*;
import com.iplant.aps.shristool.CalendarDAO;
import com.iplant.aps.utils.Constants;
import com.iplant.aps.utils.RetCode;
import com.iplant.aps.utils.aps.ExcelUtil;
import com.iplant.aps.utils.tasker.TaskTimerUtils;
import org.apache.axis.client.Call;
import org.apache.axis.encoding.XMLType;
import org.apache.commons.math3.ode.FirstOrderIntegrator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.xml.namespace.QName;
import java.io.File;
import java.io.FileOutputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
public class APSServiceImpl implements APSService {
    private static final Logger logger = LoggerFactory.getLogger(APSServiceImpl.class);

    private static APSService Instance;

    public static APSService getInstance() {
        if (Instance == null)
            Instance = new APSServiceImpl();
        return Instance;
    }

    public ServiceResult<APSManuCapacity> APS_QueryManuCapacity(BMSEmployee wLoginUser, int wID) {
        ServiceResult<APSManuCapacity> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            wResult.Result = APSManuCapacityDAO.getInstance().SelectByID(wLoginUser, wID, wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(StringUtils.Format("{0} {1} ex：{2}",
                    "APSServiceImpl", "APS_QueryManuCapacity", e.toString()));
        }
        return wResult;
    }

    public ServiceResult<List<APSManuCapacity>> APS_QueryManuCapacityList(BMSEmployee wLoginUser, int wID, int wLineID,
                                                                          int wPartID, int wActive, int wProductID) {
        ServiceResult<List<APSManuCapacity>> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            wResult.Result = APSManuCapacityDAO.getInstance().SelectList(wLoginUser, wID, wLineID, wPartID, wActive,
                    wProductID,
                    wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(StringUtils.Format("{0} {1} ex：{2}",
                    "APSServiceImpl", "APS_QueryManuCapacityList", e.toString()));
        }
        return wResult;
    }

    public ServiceResult<Long> APS_UpdateManuCapacity(BMSEmployee wLoginUser, APSManuCapacity wAPSManuCapacity) {
        ServiceResult<Long> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            wResult.Result = APSManuCapacityDAO.getInstance().Update(wLoginUser, wAPSManuCapacity, wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(StringUtils.Format("{0} {1} ex：{2}",
                    "APSServiceImpl", "APS_UpdateManuCapacity", e.toString()));
        }
        return wResult;
    }

    public ServiceResult<Integer> APS_ActiveManuCapacityList(BMSEmployee wLoginUser, List<Integer> wIDList,
                                                             int wActive) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            APSManuCapacityDAO.getInstance().Active(wLoginUser, wIDList, wActive, wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(StringUtils.Format("{0} {1} ex：{2}",
                    "APSServiceImpl", "APS_ActiveManuCapacityList", e.toString()));
        }
        return wResult;
    }

    public ServiceResult<APSDismantling> APS_QueryDismantling(BMSEmployee wLoginUser, int wID) {
        ServiceResult<APSDismantling> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            wResult.Result = APSDismantlingDAO.getInstance().SelectByID(wLoginUser, wID, wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(StringUtils.Format("{0} {1} ex：{2}",
                    "APSServiceImpl", "APS_QueryDismantling", e.toString()));
        }
        return wResult;
    }

    public ServiceResult<List<APSDismantling>> APS_QueryDismantlingList(BMSEmployee wLoginUser, int wID, int wLineID,
                                                                        int wPartID, int wProductID, int wMaterialID) {
        ServiceResult<List<APSDismantling>> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            wResult.Result = APSDismantlingDAO.getInstance().SelectList(wLoginUser, wID, wLineID, wPartID, wProductID,
                    wMaterialID, wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(StringUtils.Format("{0} {1} ex：{2}",
                    "APSServiceImpl", "APS_QueryDismantlingList", e.toString()));
        }
        return wResult;
    }

    public ServiceResult<Long> APS_UpdateDismantling(BMSEmployee wLoginUser, APSDismantling wAPSDismantling) {
        ServiceResult<Long> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            wResult.Result = APSDismantlingDAO.getInstance().Update(wLoginUser, wAPSDismantling, wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(StringUtils.Format("{0} {1} ex：{2}",
                    "APSServiceImpl", "APS_UpdateDismantling", e.toString()));
        }
        return wResult;
    }

    public ServiceResult<APSPartsLog> APS_QueryPartsLog(BMSEmployee wLoginUser, int wID) {
        ServiceResult<APSPartsLog> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            wResult.Result = APSPartsLogDAO.getInstance().SelectByID(wLoginUser, wID, wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(StringUtils.Format("{0} {1} ex：{2}",
                    "APSServiceImpl", "APS_QueryPartsLog", e.toString()));
        }
        return wResult;
    }

    public ServiceResult<List<APSPartsLog>> APS_QueryPartsLogList(BMSEmployee wLoginUser, int wID, int wProductID,
                                                                  String wPartNo) {
        ServiceResult<List<APSPartsLog>> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            wResult.Result = APSPartsLogDAO.getInstance().SelectList(wLoginUser, wID, wProductID, wPartNo, wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(StringUtils.Format("{0} {1} ex：{2}",
                    "APSServiceImpl", "APS_QueryPartsLogList", e.toString()));
        }
        return wResult;
    }

    public ServiceResult<Long> APS_UpdatePartsLog(BMSEmployee wLoginUser, APSPartsLog wAPSPartsLog) {
        ServiceResult<Long> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            wResult.Result = APSPartsLogDAO.getInstance().Update(wLoginUser, wAPSPartsLog, wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(StringUtils.Format("{0} {1} ex：{2}",
                    "APSServiceImpl", "APS_UpdatePartsLog", e.toString()));
        }
        return wResult;
    }

    public ServiceResult<APSInstallation> APS_QueryInstallation(BMSEmployee wLoginUser, int wID) {
        ServiceResult<APSInstallation> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            wResult.Result = APSInstallationDAO.getInstance().SelectByID(wLoginUser, wID, wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(StringUtils.Format("{0} {1} ex：{2}",
                    "APSServiceImpl", "APS_QueryInstallation", e.toString()));
        }
        return wResult;
    }

    public ServiceResult<List<APSInstallation>> APS_QueryInstallationList(BMSEmployee wLoginUser, int wID, int wLineID,
                                                                          int wPartID, int wMaterialID,
                                                                          int wProductID) {
        ServiceResult<List<APSInstallation>> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            wResult.Result = APSInstallationDAO.getInstance().SelectList(wLoginUser, wID, wLineID, wPartID, wMaterialID,
                    wProductID, wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(StringUtils.Format("{0} {1} ex：{2}",
                    "APSServiceImpl", "APS_QueryInstallationList", e.toString()));
        }
        return wResult;
    }

    public ServiceResult<Long> APS_UpdateInstallation(BMSEmployee wLoginUser, APSInstallation wAPSInstallation) {
        ServiceResult<Long> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            wResult.Result = APSInstallationDAO.getInstance().Update(wLoginUser, wAPSInstallation, wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(StringUtils.Format("{0} {1} ex：{2}",
                    "APSServiceImpl", "APS_UpdateInstallation", e.toString()));
        }
        return wResult;
    }

    public ServiceResult<APSTaskPart> APS_QueryTaskPart(BMSEmployee wLoginUser, int wID) {
        ServiceResult<APSTaskPart> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            wResult.Result = APSTaskPartDAO.getInstance().SelectByID(wLoginUser, wID, wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(StringUtils.Format("{0} {1} ex：{2}",
                    "APSServiceImpl", "APS_QueryTaskPart", e.toString()));
        }
        return wResult;
    }

    public ServiceResult<List<APSTaskPart>> APS_QueryTaskPartList(BMSEmployee wLoginUser, int wID, int wOrderID,
                                                                  int wTaskLineID, int wLineID, int wPartID,
                                                                  int wActive) {
        ServiceResult<List<APSTaskPart>> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wResult.Result = APSTaskPartDAO.getInstance().SelectList(wLoginUser, wID, wOrderID, wTaskLineID, wLineID,
                    wPartID, wActive, -1, null, -1, null, null, wErrorCode);

            // 处理延迟天数
            if (wResult.Result.size() > 0) {
                wResult.Result.forEach(p -> {
                    p.EndTime.add(Calendar.DATE, -1);
                    Calendar wEDate = (Calendar) p.FinishWorkTime.clone();
                    Calendar wSDate = (Calendar) p.EndTime.clone();
                    p.DelayHours = getDateDays(wEDate, wSDate);
                });
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(StringUtils.Format("{0} {1} ex：{2}",
                    "APSServiceImpl", "APS_QueryTaskPartList", e.toString()));
        }
        return wResult;
    }

    /**
     * 获取间隔天数
     */
    private double getDateDays(Calendar wSDate, Calendar wEDate) {
        double wResult = 0;
        try {
            wResult = (double) ((wEDate.getTime().getTime() - wSDate.getTime().getTime() + 1000000)
                    / (3600 * 24 * 1000));
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
        return wResult;
    }

    public ServiceResult<Long> APS_UpdateTaskPart(BMSEmployee wLoginUser, APSTaskPart wAPSTaskPart) {
        ServiceResult<Long> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            wResult.Result = APSTaskPartDAO.getInstance().Update(wLoginUser, wAPSTaskPart, wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(StringUtils.Format("{0} {1} ex：{2}",
                    "APSServiceImpl", "APS_UpdateTaskPart", e.toString()));
        }
        return wResult;
    }

    public ServiceResult<Integer> APS_ActiveTaskPartList(BMSEmployee wLoginUser, List<Integer> wIDList, int wActive) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            APSTaskPartDAO.getInstance().Active(wLoginUser, wIDList, wActive, wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(StringUtils.Format("{0} {1} ex：{2}",
                    "APSServiceImpl", "APS_ActiveTaskPartList", e.toString()));
        }
        return wResult;
    }

    public ServiceResult<APSTaskLine> APS_QueryTaskLine(BMSEmployee wLoginUser, int wID) {
        ServiceResult<APSTaskLine> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            wResult.Result = APSTaskLineDAO.getInstance().SelectByID(wLoginUser, wID, wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(StringUtils.Format("{0} {1} ex：{2}",
                    "APSServiceImpl", "APS_QueryTaskLine", e.toString()));
        }
        return wResult;
    }

    public ServiceResult<List<APSTaskLine>> APS_QueryTaskLineList(BMSEmployee wLoginUser, int wID, int wOrderID,
                                                                  int wWorkShopID, int wLineID, int wActive) {
        ServiceResult<List<APSTaskLine>> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            wResult.Result = APSTaskLineDAO.getInstance().SelectList(wLoginUser, wID, wOrderID, wWorkShopID, wLineID,
                    wActive, wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(StringUtils.Format("{0} {1} ex：{2}",
                    "APSServiceImpl", "APS_QueryTaskLineList", e.toString()));
        }
        return wResult;
    }

    public ServiceResult<Long> APS_UpdateTaskLine(BMSEmployee wLoginUser, APSTaskLine wAPSTaskLine) {
        ServiceResult<Long> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            wResult.Result = APSTaskLineDAO.getInstance().Update(wLoginUser, wAPSTaskLine, wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(StringUtils.Format("{0} {1} ex：{2}",
                    "APSServiceImpl", "APS_UpdateTaskLine", e.toString()));
        }
        return wResult;
    }

    public ServiceResult<Integer> APS_ActiveTaskLineList(BMSEmployee wLoginUser, List<Integer> wIDList, int wActive) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            APSTaskLineDAO.getInstance().Active(wLoginUser, wIDList, wActive, wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(StringUtils.Format("{0} {1} ex：{2}",
                    "APSServiceImpl", "APS_ActiveTaskLineList", e.toString()));
        }
        return wResult;
    }

    public ServiceResult<List<OMSOrder>> APS_SetOrderPriority(BMSEmployee wLoginUser, List<OMSOrder> wOrderList,
                                                              List<OMSOrderPriority> wOrderPriorityList,
                                                              List<Integer> wLineOrders, List<Integer> wCustomerOrders,
                                                              List<Integer> wProductIDs) {
        ServiceResult<List<OMSOrder>> wResult = new ServiceResult<>();
        try {
            wResult.Result = APSAutoUtils.getInstance().APS_SetOrderPriority(wOrderList, wOrderPriorityList,
                    wLineOrders, wCustomerOrders, wProductIDs);
        } catch (Exception e) {
            logger.error(StringUtils.Format("{0} {1} ex：{2}",
                    "APSServiceImpl", "APS_SetOrderPriority", e.toString()));
        }
        return wResult;
    }

    public ServiceResult<List<APSTaskPart>> APS_AutoTaskPart(BMSEmployee wLoginUser, List<OMSOrder> wOrderList,
                                                             APSShiftPeriod wShiftPeriod,
                                                             List<APSTaskPart> wOrderPartIssuedList,
                                                             List<OMSOutsourceOrder> wOutsourceOrderList,
                                                             Calendar wStartTime, Calendar wEndTime,
                                                             Map<Integer, List<FPCRoutePart>> wRoutePartList,
                                                             List<APSManuCapacity> wManuCapacityList,
                                                             List<APSInstallation> wAPSInstallationList,
                                                             List<APSDismantling> wAPSDismantlingList,
                                                             List<APSMessage> wMessageList, int wWorkDay,
                                                             int wLimitMinutes, List<APSTaskPart> wMutualTaskList) {
        ServiceResult<List<APSTaskPart>> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            wResult.Result = new ArrayList<>();

            List<FMCTimeZone> wAllZoneList;
            Map<Integer, List<CFGCalendar>> wCalendarMap;

            wAllZoneList = APSUtils.getInstance().GetTimeZoneListAndHolidayList(wLoginUser, wWorkDay);

            wCalendarMap = APSUtils.getInstance().GetCalendarMap(wLoginUser);

            wResult.Result = APSAutoUtils.getInstance().APS_AutoTaskPart(wLoginUser, wOrderList, wShiftPeriod,
                    wOrderPartIssuedList, wOutsourceOrderList, wStartTime, wEndTime, wRoutePartList, wManuCapacityList,
                    wAPSInstallationList, wAPSDismantlingList, wMessageList, wWorkDay, wAllZoneList, wCalendarMap,
                    wLimitMinutes, wMutualTaskList, wErrorCode);

            if (wResult.Result != null && (wResult.Result).size() > 0 && wShiftPeriod == APSShiftPeriod.Week) {
                List<APSTaskPart> wRemoveList = new ArrayList<>();
                for (APSTaskPart wAPSTaskPart : wResult.Result) {
                    List<APSTaskPart> wList = APSTaskPartDAO.getInstance().SelectList(wLoginUser, -1,
                            wAPSTaskPart.OrderID, -1, wAPSTaskPart.LineID, wAPSTaskPart.PartID, 1,
                            wShiftPeriod.getValue(),
                            new ArrayList<>(Arrays.asList(APSTaskStatus.Confirm.getValue(),
                                    APSTaskStatus.Started.getValue(),
                                    APSTaskStatus.Done.getValue())),
                            -1, null, null, wErrorCode);
                    if (wList != null && wList.size() > 0) {
                        wRemoveList.add(wAPSTaskPart);
                    }
                }
                wResult.Result.removeIf(wRemoveList::contains);
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(StringUtils.Format("{0} {1} ex：{2}",
                    "APSServiceImpl", "APS_AutoTaskPart", e.toString()));
        }
        return wResult;
    }

    public ServiceResult<List<APSMessage>> APS_CheckTaskPart(BMSEmployee wLoginUser, List<OMSOrder> wOrderList,
                                                             List<APSTaskPart> wCheckTaskList,
                                                             APSShiftPeriod wShiftPeriod,
                                                             List<APSTaskPart> wOrderPartIssuedList,
                                                             List<OMSOutsourceOrder> wOutsourceOrderList,
                                                             Calendar wStartTime, Calendar wEndTime,
                                                             Map<Integer, List<FPCRoutePart>> wRoutePartList,
                                                             List<APSManuCapacity> wManuCapacityList,
                                                             List<APSInstallation> wAPSInstallationList,
                                                             List<APSDismantling> wAPSDismantlingList, int wWorkDay) {
        ServiceResult<List<APSMessage>> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            List<FMCTimeZone> wAllZoneList;
            Map<Integer, List<CFGCalendar>> wCalendarMap;

            wAllZoneList = APSUtils.getInstance().GetTimeZoneListAndHolidayList(wLoginUser, wWorkDay);

            wCalendarMap = APSUtils.getInstance().GetCalendarMap(wLoginUser);

            wResult.Result = APSManualUtils.getInstance().APS_CheckTaskPart(wLoginUser, wOrderList, wCheckTaskList,
                    wShiftPeriod, wOrderPartIssuedList, wOutsourceOrderList, wStartTime, wEndTime, wRoutePartList,
                    wManuCapacityList, wAPSInstallationList, wAPSDismantlingList, wWorkDay, wAllZoneList, wCalendarMap,
                    wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(StringUtils.Format("{0} {1} ex：{2}",
                    "APSServiceImpl", "APS_CheckTaskPart", e.toString()));
        }
        return wResult;
    }

    public ServiceResult<APSMessage> APS_QueryMessage(BMSEmployee wLoginUser, int wID) {
        ServiceResult<APSMessage> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            wResult.Result = APSMessageDAO.getInstance().SelectByID(wLoginUser, wID, wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(StringUtils.Format("{0} {1} ex：{2}",
                    "APSServiceImpl", "APS_QueryMessage", e.toString()));
        }
        return wResult;
    }

    public ServiceResult<List<APSMessage>> APS_QueryMessageList(BMSEmployee wLoginUser, int wID, int wOrderID) {
        ServiceResult<List<APSMessage>> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            wResult.Result = APSMessageDAO.getInstance().SelectList(wLoginUser, wID, wOrderID, wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(StringUtils.Format("{0} {1} ex：{2}",
                    "APSServiceImpl", "APS_QueryMessageList", e.toString()));
        }
        return wResult;
    }

    public ServiceResult<Long> APS_UpdateMessage(BMSEmployee wLoginUser, APSMessage wAPSMessage) {
        ServiceResult<Long> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            wResult.Result = APSMessageDAO.getInstance().Update(wLoginUser, wAPSMessage, wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(StringUtils.Format("{0} {1} ex：{2}",
                    "APSServiceImpl", "APS_UpdateMessage", e.toString()));
        }
        return wResult;
    }

    public ServiceResult<List<APSTaskPart>> APS_QueryTaskPartList(BMSEmployee wLoginUser, int wShiftPeriod,
                                                                  List<Integer> wStatusIDList,
                                                                  List<Integer> wOrderIDList) {
        ServiceResult<List<APSTaskPart>> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            wResult.Result = APSTaskPartDAO.getInstance().SelectListByOrderIDList(wLoginUser, wShiftPeriod,
                    wStatusIDList, wOrderIDList, wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(StringUtils.Format("{0} {1} ex：{2}",
                    "APSServiceImpl", "APS_QueryTaskPartList", e.toString()));
        }
        return wResult;
    }

    public ServiceResult<List<APSTaskStep>> APS_QueryTaskStepByShiftDate(BMSEmployee wLoginUser, Calendar wShiftDate,
                                                                         int wWork) {
        ServiceResult<List<APSTaskStep>> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            FMCShiftLevel wShiftLevel = MESServer.MES_QueryShiftLevel(wLoginUser, 0);
            int wShiftID = MESServer.MES_QueryShiftID(0, wShiftDate, APSShiftPeriod.Day, wShiftLevel, 0);

            APIResult wApiResult = LFSServiceImpl.getInstance().LFS_QueryWorkAreaStationList(wLoginUser);
            List<LFSWorkAreaStation> wWorkAreaStationList = wApiResult.List(LFSWorkAreaStation.class);
            List<Integer> wPartIDList = new ArrayList<>();
            for (LFSWorkAreaStation wWorkAreaStation : wWorkAreaStationList) {
                if (wPartIDList.contains(wWorkAreaStation.StationID))
                    continue;
                wPartIDList.add(wWorkAreaStation.StationID);
            }

            List<APSTaskStep> wList = APSTaskStepDAO.getInstance().SelectList(wLoginUser, -1, -1, -1, -1, -1, -1, -1,
                    -1, wShiftID, 1, null, null, null, null, wErrorCode);
            if (wList != null && wList.size() > 0) {
                wList = wList.stream().filter(p -> wPartIDList.stream().anyMatch(q -> q == p.PartID))
                        .collect(Collectors.toList());
            }
            wResult.Result = wList;
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(StringUtils.Format("{0} {1} ex：{2}",
                    "APSServiceImpl", "APS_QueryTaskStepByShiftDate", e.toString()));
        }

        return wResult;
    }

    @Override
    public ServiceResult<List<APSTaskStep>> APS_CreateTaskStepByShiftDate(BMSEmployee wLoginUser, Calendar wShiftDate) {
        ServiceResult<List<APSTaskStep>> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>();

            Calendar wShiftEnd = CalendarUtil.GetDate(wShiftDate);
            wShiftEnd.set(Calendar.HOUR_OF_DAY, 23);
            wShiftEnd.set(Calendar.MINUTE, 59);
            wShiftEnd.set(Calendar.SECOND, 59);

            // 班次
            int wShiftID = MESServer.MES_QueryShiftID(0, wShiftDate, APSShiftPeriod.Day, FMCShiftLevel.Day, 0);

            // 查询当天包括之前未完成（下达的,激活的,开始的）的周计划wShiftDate
            List<APSTaskPart> wAPSTaskPartList = APSTaskPartDAO.getInstance().SelectList(wLoginUser, -1, -1, -1, -1, -1,
                    1, APSShiftPeriod.Week.getValue(),
                    new ArrayList<>(Arrays.asList(APSTaskStatus.Issued.getValue(),
                            APSTaskStatus.Confirm.getValue(), APSTaskStatus.Started.getValue())),
                    -1, null, wShiftEnd, wErrorCode);
            if (wAPSTaskPartList == null || wAPSTaskPartList.size() <= 0)
                return wResult;

            // 将相同订单、相同工位的工位计划剔除
            wAPSTaskPartList = this.RemoveSameTaskPart(wAPSTaskPartList);

            // 获取对应所有已存在的工序任务
            List<APSTaskStep> wAPSTaskStepList = new ArrayList<>();
            for (APSTaskPart wItem : wAPSTaskPartList) {
                wAPSTaskStepList.addAll(APSTaskStepDAO.getInstance().SelectList(wLoginUser, -1, -1, -1, wItem.ID, -1,
                        -1, -1, -1, -1, 1, null, null, null, null, wErrorCode));
            }

            // 根据工位对应的所有工序生成所有未做完的工序任务 今天已排的工序任务从已排任务中获取 待排计划状态为0 已排计划中有保存和下达状态
            List<APSTaskStep> wAPSTaskStepUndoList = new ArrayList<>();
            // 工艺数据
            List<FPCRoutePart> wFPCRoutePartList = FMCServiceImpl.getInstance()
                    .FPC_QueryRoutePartListByRouteID(BaseDAO.SysAdmin, 0).List(FPCRoutePart.class);
            List<FPCRoutePartPoint> wFPCRoutePartPointList = FMCServiceImpl.getInstance()
                    .FPC_QueryRoutePartPointListByRouteID(BaseDAO.SysAdmin, 0, 0).List(FPCRoutePartPoint.class);

            Calendar wBaseTime = Calendar.getInstance();
            wBaseTime.set(2000, 0, 1);

            List<Integer> wPartPointIDList = null;
            Optional<APSTaskStep> wOption = Optional.empty();

            // 根据权限返回数据
            // 工区人员
            List<LFSWorkAreaChecker> wAreaCheckerList = APSConstans.GetLFSWorkAreaCheckerList();
            if (wAreaCheckerList != null && wAreaCheckerList.stream().anyMatch(
                    p -> p.LeaderIDList != null && p.LeaderIDList.stream().anyMatch(q -> q == wLoginUser.ID))) {
                // 工区工位
                List<LFSWorkAreaStation> wAreaStationList = new ArrayList<>(
                        APSConstans.GetLFSWorkAreaStationList().values());
                int wAreaID = wAreaCheckerList.stream().filter(
                                p -> p.LeaderIDList != null && p.LeaderIDList.stream().anyMatch(q -> q == wLoginUser.ID))
                        .findFirst().get().WorkAreaID;
                List<LFSWorkAreaStation> wTempList = wAreaStationList.stream().filter(p -> p.WorkAreaID == wAreaID)
                        .collect(Collectors.toList());
                if (wTempList.size() > 0) {
                    wAPSTaskPartList = wAPSTaskPartList.stream()
                            .filter(p -> wTempList.stream().anyMatch(q -> q.StationID == p.PartID))
                            .collect(Collectors.toList());
                } else {
                    wAPSTaskPartList = new ArrayList<>();
                }
            } else {
                wAPSTaskPartList = new ArrayList<>();
            }

            int wRouteID = 0;
            List<Integer> wOrderIDList = wAPSTaskPartList.stream().map(p -> p.OrderID).distinct()
                    .collect(Collectors.toList());

            List<OMSOrder> wOMSOrderList = OMSOrderDAO.getInstance().SelectListByIDList(wLoginUser, wOrderIDList,
                    wErrorCode);
            Map<Integer, OMSOrder> wOMSOrderMap = wOMSOrderList.stream().collect(Collectors.toMap(p -> p.ID, p -> p));
            OMSOrder wOrder = null;
            for (APSTaskPart wItem : wAPSTaskPartList) {
                wOrder = null;
                if (wOMSOrderMap.containsKey(wItem.OrderID)) {
                    wOrder = wOMSOrderMap.get(wItem.OrderID);
                }
                if (wOrder != null && wOrder.ID > 0) {
                    wRouteID = wOrder.RouteID;
                }

                if (wRouteID <= 0) {
                    if (wOrder != null) {
                        wResult.FaultCode += StringUtils.Format("提示：【{0}】该订单工艺BOP缺失!", wOrder.OrderNo);
                    }
                    return wResult;
                }
                // 获取工序ID集合
                wPartPointIDList = APS_GetPartPointIDList(wFPCRoutePartList, wFPCRoutePartPointList, wItem.PartID,
                        wRouteID);
                if (wPartPointIDList == null || wPartPointIDList.size() <= 0) {
                    continue;
                }

                for (int wPartPointID : wPartPointIDList) {
                    wOption = wAPSTaskStepList.stream()
                            .filter(p -> p.TaskPartID == wItem.ID && p.StepID == wPartPointID).findFirst();
                    if (wOption.isPresent()) {
                        wAPSTaskStepUndoList.add(wOption.get());
                    } else {
                        APSTaskStep wAPSTaskStep = new APSTaskStep();

                        wAPSTaskStep.Active = 1;
                        wAPSTaskStep.ID = 0;
                        wAPSTaskStep.LineID = wItem.LineID;
                        wAPSTaskStep.MaterialNo = wItem.MaterialNo;
                        wAPSTaskStep.OrderID = wItem.OrderID;
                        wAPSTaskStep.PartID = wItem.PartID;
                        wAPSTaskStep.PartNo = wItem.PartNo;
                        wAPSTaskStep.PlanerID = wLoginUser.ID;
                        wAPSTaskStep.ProductNo = wItem.ProductNo;
                        wAPSTaskStep.ShiftID = wShiftID;
                        wAPSTaskStep.Status = APSTaskStatus.Saved.getValue();
                        wAPSTaskStep.StepID = wPartPointID;
                        wAPSTaskStep.TaskPartID = wItem.ID;
                        wAPSTaskStep.TaskLineID = wItem.TaskLineID;
                        wAPSTaskStep.TaskText = wItem.TaskText;
                        wAPSTaskStep.WorkHour = 0;
                        wAPSTaskStep.WorkShopID = wItem.WorkShopID;
                        wAPSTaskStep.StartTime = wBaseTime;
                        wAPSTaskStep.EndTime = wBaseTime;
                        wAPSTaskStep.ReadyTime = wBaseTime;
                        wAPSTaskStep.CreateTime = Calendar.getInstance();

                        wAPSTaskStep.ID = APSTaskStepDAO.getInstance().Update(wLoginUser, wAPSTaskStep, wErrorCode);

                        wAPSTaskStepUndoList.add(wAPSTaskStep);
                    }
                }
            }

            ServiceResult<List<OMSOrder>> wOrderResult = this.GetOrderListAndTaskPartListByTaskStepList(wLoginUser,
                    wAPSTaskStepUndoList, wFPCRoutePartList, wFPCRoutePartPointList);
            wResult.CustomResult.put("OrderList", wOrderResult.Result);
            wResult.Result = wAPSTaskStepUndoList;

            // 处理制定的数据，只要未排的
            List<APSTaskPartDetails> wToDoList = new ArrayList<>();
            List<APSTaskPartDetails> wList = (List<APSTaskPartDetails>) wOrderResult.CustomResult.get("TaskPartList");
            for (APSTaskPartDetails wAPSTaskPartDetails : wList) {
                if (wResult.Result.stream().anyMatch(p -> p.TaskPartID == wAPSTaskPartDetails.APSTaskPart.ID
                        && p.Status == APSTaskStatus.Saved.getValue())) {
                    wToDoList.add(wAPSTaskPartDetails);
                }
            }

            wResult.CustomResult.put("TaskPartList", wToDoList);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception ex) {
            logger.error(StringUtils.Format("{0} {1} ex：{2}", "APSServiceImpl", "APS_CreateTaskStepByShiftDate",
                    ex.toString()));
        }
        return wResult;
    }

    /**
     * 将相同订单、相同工位的工位计划去重
     */
    private List<APSTaskPart> RemoveSameTaskPart(List<APSTaskPart> wAPSTaskPartList) {
        List<APSTaskPart> wResult = new ArrayList<>();
        try {
            if (wAPSTaskPartList == null || wAPSTaskPartList.size() <= 0) {
                return wResult;
            }

            List<APSTaskPart> wList;
            Optional<APSTaskPart> wOption = Optional.empty();
            for (APSTaskPart wAPSTaskPart : wAPSTaskPartList) {
                wList = wAPSTaskPartList.stream()
                        .filter(p -> p.OrderID == wAPSTaskPart.OrderID && p.PartID == wAPSTaskPart.PartID)
                        .collect(Collectors.toList());
                if (wList.size() == 1) {
                    wResult.add(wAPSTaskPart);
                } else if (wList.size() > 1) {
                    wOption = wList.stream().max(Comparator.comparing(a -> a.SubmitTime));
                    wResult.add(wOption.get());
                }
            }
            // 去重
            wResult = new ArrayList<>(wResult.stream()
                    .collect(Collectors.toMap(APSTaskPart::getID, account -> account, (k1, k2) -> k2)).values());
        } catch (Exception ex) {
            logger.error(StringUtils.Format("{0} {1} ex：{2}", "APSServiceImpl", "RemoveSameTaskPart", ex.toString()));
        }
        return wResult;
    }

    /**
     * 根据修程、车型、工位获取工序ID集合
     *
     * @param wFPCRoutePartList      工位工艺列表
     * @param wFPCRoutePartPointList 工序工艺列表
     * @param wPartID                工位ID
     * @param wRouteID               修程
     * @return 工序ID集合
     */
    private List<Integer> APS_GetPartPointIDList(List<FPCRoutePart> wFPCRoutePartList,
                                                 List<FPCRoutePartPoint> wFPCRoutePartPointList, int wPartID,
                                                 int wRouteID) {
        List<Integer> wResult = new ArrayList<>();
        try {

            Optional<FPCRoutePart> wPartOption = wFPCRoutePartList.stream()
                    .filter(p -> p.RouteID == wRouteID && p.PartID == wPartID).findFirst();
            if (!wPartOption.isPresent()) {
                return wResult;
            }

            FPCRoutePart wFPCRoutePart = wPartOption.get();

            List<FPCRoutePartPoint> wList = wFPCRoutePartPointList.stream()
                    .filter(p -> p.PartID == wFPCRoutePart.PartID && p.RouteID == wRouteID)
                    .collect(Collectors.toList());

            if (wList.size() <= 0) {
                return wResult;
            }

            wResult = wList.stream().map(p -> p.PartPointID).collect(Collectors.toList());
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<Map<String, Object>>> APS_QueryTableInfoList(BMSEmployee wLoginUser, Calendar wStartTime,
                                                                           Calendar wEndTime, int wAPSShiftPeriod) {
        ServiceResult<List<Map<String, Object>>> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            // 生成shiftID
            FMCShiftLevel wShiftLevel = MESServer.MES_QueryShiftLevel(wLoginUser, 0);
            int wShiftID = MESServer.MES_QueryShiftID(0, wStartTime, APSShiftPeriod.getEnumType(wAPSShiftPeriod),
                    wShiftLevel, 0);
            // 工区工位列表
            APIResult wApiResult = LFSServiceImpl.getInstance().LFS_QueryWorkAreaStationList(wLoginUser);
            List<LFSWorkAreaStation> wWorkAreaStationList = wApiResult.List(LFSWorkAreaStation.class);
            // 根据ShiftID查询任务
            List<APSTaskPart> wList = APSTaskPartDAO.getInstance().SelectListByShiftID(wLoginUser, wShiftID,
                    wErrorCode);
            // 获取最大的SubmitTime
            Calendar wMaxSubmitTime = wList.stream().max(Comparator.comparing(APSTaskPart::getSubmitTime))
                    .get().SubmitTime;
            // 月计划任务集合
            wList = wList.stream().filter(p -> p.SubmitTime.compareTo(wMaxSubmitTime) == 0)
                    .collect(Collectors.toList());
            // 月订单集合
            List<OMSOrder> wOrderList = OMSServiceImpl.getInstance().OMS_QueryHistoryOrderList(wLoginUser, wStartTime,
                    wEndTime, APSShiftPeriod.Week.getValue()).Result;
            // 生成表头数据
            List<FPCPart> wPartList = CoreServiceImpl.getInstance().FPC_QueryPartList(wLoginUser).List(FPCPart.class);
            int wFlag = 0;
            Map<String, Object> wHeadMap = new HashMap<>();
            wHeadMap.put(String.valueOf(wFlag++), "序号");
            wHeadMap.put(String.valueOf(wFlag++), "车型");
            wHeadMap.put(String.valueOf(wFlag++), "车号");
            wHeadMap.put(String.valueOf(wFlag++), "配属");
            wHeadMap.put(String.valueOf(wFlag++), "修程");
            for (LFSWorkAreaStation wItem : wWorkAreaStationList) {
                Optional<FPCPart> wOption = wPartList.stream().filter(p -> p.ID == wItem.StationID).findFirst();
                if (wOption.isPresent()) {
                    wHeadMap.put(String.valueOf(wFlag++), wOption.get().Name);
                }
            }
            wHeadMap.put(String.valueOf(wFlag++), "停时");
            wHeadMap.put(String.valueOf(wFlag++), "备注");
            wResult.Result.add(wHeadMap);
            // 获取表格数据
            wResult.Result.addAll(ChangeToTable(wOrderList, wList, wWorkAreaStationList).Result);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(
                    StringUtils.Format("{0} {1} ex：{2}", "APSServiceImpl", "APS_QueryTableInfoList", e.toString()));
        }
        return wResult;
    }

    /**
     * @param wOrderList       月度订单
     * @param wAPSTaskPartList 月计划列表
     * @param wStationList     工区工位列表（gantt中左边显示的工位列表）
     */
    @Override
    public ServiceResult<List<Map<String, Object>>> ChangeToTable(List<OMSOrder> wOrderList,
                                                                  List<APSTaskPart> wAPSTaskPartList,
                                                                  List<LFSWorkAreaStation> wStationList) {
        ServiceResult<List<Map<String, Object>>> wResult = new ServiceResult<>();
        try {
            if (wOrderList == null || wAPSTaskPartList == null || wStationList == null) {
                wResult.FaultCode += "参数不合法 转换Table失败！";
                return wResult;
            }
            wResult.Result = new ArrayList<>();
            // 排序
            wStationList.sort(Comparator.comparing(LFSWorkAreaStation::getOrderNum));
            // 查询月计划
            Map<Integer, List<APSTaskPart>> wAPSTaskPartMap = wAPSTaskPartList.stream()
                    .collect(Collectors.groupingBy(APSTaskPart::getOrderID));
            Map<Integer, APSTaskPart> wTaskMap;
            Map<String, Object> wMap;
            Calendar wBaseTime = Calendar.getInstance();
            wBaseTime.set(2000, 1, 1);
            for (OMSOrder wOMSOrder : wOrderList) {
                wMap = CloneTool.Clone(wOMSOrder, Map.class);
                if (wAPSTaskPartMap.containsKey(wOMSOrder.ID)) {
                    wTaskMap = wAPSTaskPartMap.get(wOMSOrder.ID).stream()
                            .collect(Collectors.toMap(p -> p.PartID, p -> p, (k1, k2) -> k1));
                } else {
                    wTaskMap = new HashMap<>();
                }

                for (LFSWorkAreaStation wStation : wStationList) {

                    if (!wTaskMap.containsKey(wStation.StationID)) {
                        wMap.put("Station_" + wStation.StationID, wBaseTime);
                        wMap.put("Status_" + wStation.StationID, APSTaskStatus.Default.getValue());
                        continue;
                    }

                    APSTaskPart apsTaskPart = wTaskMap.get(wStation.StationID);

                    if (apsTaskPart.Status == 5) {
                        wMap.put("Status_" + wStation.StationID, 5);
                    } else {
                        SimpleDateFormat wSDF = new SimpleDateFormat("yyyyMMdd");
                        int wRShiftID = Integer.parseInt(wSDF.format(Calendar.getInstance().getTime()));
                        Calendar wCloneEndTime = (Calendar) apsTaskPart.EndTime.clone();
                        wCloneEndTime.add(Calendar.HOUR_OF_DAY, -12);

                        int wPShiftID = Integer.parseInt(wSDF.format(wCloneEndTime.getTime()));

                        if (apsTaskPart.Status == 2) {
                            wMap.put("Status_" + wStation.StationID, 2);
                        } else {
                            if (wRShiftID > wPShiftID) {
                                wMap.put("Status_" + wStation.StationID, 6);
                            } else {
                                wMap.put("Status_" + wStation.StationID, apsTaskPart.getStatus());
                            }
                        }
                    }

                    // 赋值tip

                    if (apsTaskPart.getStatus() == APSTaskStatus.Done.getValue()) {
                        wMap.put("Station_" + wStation.StationID, apsTaskPart.FinishWorkTime);
                        continue;
                    }

                    wMap.put("Station_" + wStation.StationID, apsTaskPart.EndTime);
                }
                wResult.Result.add(wMap);
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
        return wResult;
    }

    public ServiceResult<List<Map<String, Object>>> ChangeToTableByEndTime(List<OMSOrder> wOrderList,
                                                                           List<APSTaskPart> wAPSTaskPartList,
                                                                           List<LFSWorkAreaStation> wStationList) {
        ServiceResult<List<Map<String, Object>>> wResult = new ServiceResult<>();
        try {
            wResult.Result = new ArrayList<>();

            wStationList.sort(Comparator.comparing(LFSWorkAreaStation::getOrderNum));

            Map<Integer, List<APSTaskPart>> wAPSTaskPartMap = wAPSTaskPartList
                    .stream().collect(Collectors.groupingBy(APSTaskPart::getOrderID));
            Map<Integer, APSTaskPart> wTaskMap;
            Map<String, Object> wMap;
            Calendar wBaseTime = Calendar.getInstance();
            wBaseTime.set(2000, 1, 1);
            for (OMSOrder wOMSOrder : wOrderList) {
                wMap = CloneTool.Clone(wOMSOrder, Map.class);
                if (wAPSTaskPartMap.containsKey(wOMSOrder.ID)) {
                    wTaskMap = (wAPSTaskPartMap.get(wOMSOrder.ID)).stream()
                            .collect(Collectors.toMap(p -> p.PartID, p -> p, (k1, k2) -> k1));
                } else {
                    wTaskMap = new HashMap<>();
                }

                for (LFSWorkAreaStation wStation : wStationList) {

                    if (wTaskMap.containsKey(wStation.StationID)) {
                        APSTaskPart wTaskPart = wTaskMap.get(wStation.StationID);
                        if (wTaskPart.Status == 5) {
                            wMap.put("Station_" + wStation.StationID, wTaskPart.FinishWorkTime);
                        } else {
                            wMap.put("Station_" + wStation.StationID, wTaskPart.EndTime);
                        }
                    } else {
                        wMap.put("Station_" + wStation.StationID, wBaseTime);
                    }

                    // 赋值状态
                    if (wTaskMap.containsKey(wStation.StationID)) {
                        APSTaskPart apsTaskPart = wTaskMap.get(wStation.StationID);

                        if (apsTaskPart.Status == 5) {
                            wMap.put("Status_" + wStation.StationID, 5);
                        } else {
                            SimpleDateFormat wSDF = new SimpleDateFormat("yyyyMMdd");
                            int wRShiftID = Integer.parseInt(wSDF.format(Calendar.getInstance().getTime()));

                            Calendar wTime = (Calendar) apsTaskPart.EndTime.clone();
                            wTime.add(Calendar.HOUR_OF_DAY, -12);

                            int wPShiftID = Integer.parseInt(wSDF.format(wTime.getTime()));

                            if (apsTaskPart.Status == 2) {
                                wMap.put("Status_" + wStation.StationID, 2);
                            } else {
                                if (wRShiftID > wPShiftID) {
                                    wMap.put("Status_" + wStation.StationID, 6);
                                } else {
                                    wMap.put("Status_" + wStation.StationID, apsTaskPart.getStatus());
                                }

                            }
                        }
                    } else {
                        wMap.put("Status_" + wStation.StationID, 0);
                    }
                }
                wResult.Result.add(wMap);
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
        return wResult;
    }

    public ServiceResult<APSTaskStep> APS_QueryTaskStep(BMSEmployee wLoginUser, int wID) {
        ServiceResult<APSTaskStep> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            wResult.Result = APSTaskStepDAO.getInstance().SelectByID(wLoginUser, wID, wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(StringUtils.Format("{0} {1} ex：{2}",
                    "APSServiceImpl", "APS_QueryTaskStep", e.toString()));
        }
        return wResult;
    }

    public ServiceResult<List<APSTaskStep>> APS_QueryTaskStepList(BMSEmployee wLoginUser, int wID, int wOrderID,
                                                                  int wTaskLineID, int wTaskPartID, int wWorkShopID,
                                                                  int wLineID, int wPartID, int wStepID, int wShiftID,
                                                                  int wActive, List<Integer> wStateIDList) {
        ServiceResult<List<APSTaskStep>> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            wResult.Result = APSTaskStepDAO.getInstance().SelectList(wLoginUser, wID, wOrderID, wTaskLineID,
                    wTaskPartID, wWorkShopID, wLineID, wPartID, wStepID, wShiftID, wActive, wStateIDList, null, null,
                    null, wErrorCode);

            for (APSTaskStep wAPSTaskStep : wResult.Result) {
                List<SFCTaskStep> sfcTaskSteps = SFCTaskStepDAO.getInstance().SelectList(wLoginUser, -1,
                        wAPSTaskStep.ID, -1, -1, -1, null, -1, wErrorCode);
                if (sfcTaskSteps.size() > 0) {
                    wAPSTaskStep.MonitorName = APSConstans.GetBMSEmployeeName(sfcTaskSteps.get(0).MonitorID);
                }
            }
            // 查询工时
            List<APSTaskStep> wUpdateList = new ArrayList<>();

            Map<Integer, OMSOrder> wOrderMap = new HashMap<>();
            if (wResult.Result.size() > 0) {
                List<Integer> wOrderIDList = wResult.Result.stream().filter(p -> p.WorkHour > 0 && p.OrderID > 0)
                        .map(p -> p.OrderID).distinct().collect(Collectors.toList());

                if (wOrderIDList.size() > 0) {
                    wOrderMap = OMSOrderDAO.getInstance().SelectListByIDList(wLoginUser, wOrderIDList, wErrorCode)
                            .stream().collect(Collectors.toMap(p -> p.ID, p -> p));
                }

            }

            for (APSTaskStep wAPSTaskStep : wResult.Result) {
                if (wAPSTaskStep.WorkHour > 0) {
                    continue;
                }

                if (!wOrderMap.containsKey(wAPSTaskStep.OrderID))
                    continue;
                OMSOrder wOrder = wOrderMap.get(wAPSTaskStep.OrderID);
                if (wOrder == null || wOrder.ID <= 0)
                    continue;

                double wWorkHour = APSTaskStepDAO.getInstance().GetActualPeriod(wLoginUser, wOrder.RouteID,
                        wAPSTaskStep.PartID, wAPSTaskStep.StepID, wErrorCode);
                if (wWorkHour > 0) {
                    wAPSTaskStep.WorkHour = wWorkHour;
                    wUpdateList.add(wAPSTaskStep);
                }

            }

            for (APSTaskStep wAPSTaskStep : wUpdateList) {
                APSTaskStepDAO.getInstance().Update(wLoginUser, wAPSTaskStep, wErrorCode);
            }

            wResult.Result.removeIf(p -> p.Active == 2);

            ExecutorService wES = Executors.newFixedThreadPool(1);
            wES.submit(() -> AutoFinishTaskPart(wResult.Result));
            wES.shutdown();

            // 处理已取消的工序任务状态
            if (wOrderID > 0 && wPartID > 0) {
                List<APSTaskStepCancelLogBPM> apsTaskStepCancelLogBPMS = APSTaskStepCancelLogBPMDAO.getInstance()
                        .SelectList(wLoginUser, -1, "", -1, wOrderID,
                                wPartID, null, null, null, -1, wErrorCode);
                apsTaskStepCancelLogBPMS = apsTaskStepCancelLogBPMS.stream().filter(p -> p.Status == 20)
                        .collect(Collectors.toList());
                if (apsTaskStepCancelLogBPMS.size() > 0) {
                    for (APSTaskStep apsTaskStep : wResult.Result) {
                        if (apsTaskStepCancelLogBPMS.stream().anyMatch(p -> StringUtils.parseIntList(p.StepIDs.split(
                                ",")).stream().anyMatch(q -> q == apsTaskStep.StepID))) {
                            apsTaskStep.Status = APSTaskStatus.Aborted.getValue();
                            apsTaskStep.StatusText = APSTaskStatus.Aborted.getLable();
                        }
                    }
                }
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(StringUtils.Format("{0} {1} ex：{2}",
                    "APSServiceImpl", "APS_QueryTaskStepList", e.toString()));
        }
        return wResult;
    }

    private void AutoFinishTaskPart(List<APSTaskStep> wAPSTaskStepList) {
        try {
            if (wAPSTaskStepList == null || wAPSTaskStepList.size() <= 0) {
                return;
            }

            if (!wAPSTaskStepList.stream().allMatch(p -> p.Status == APSTaskStatus.Done.getValue())) {
                return;
            }
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            APSTaskPart wTaskPart = APSTaskPartDAO.getInstance().SelectByID(BaseDAO.SysAdmin,
                    wAPSTaskStepList.get(0).TaskPartID, wErrorCode);
            if (wTaskPart == null || wTaskPart.ID <= 0 || wTaskPart.Status == APSTaskStatus.Done.getValue()) {
                return;
            }

            boolean wIsTurnOrder = APSTaskPartDAO.getInstance().IsTaskPartTurnOrdered(BaseDAO.SysAdmin,
                    wAPSTaskStepList.get(0).OrderID, wAPSTaskStepList.get(0).PartID, wErrorCode);
            if (!wIsTurnOrder) {
                return;
            }

            Calendar wBaseTime = Calendar.getInstance();
            wBaseTime.set(2010, 0, 1, 0, 0, 0);
            if (wTaskPart.StartWorkTime.compareTo(wBaseTime) <= 0) {
                wTaskPart.StartWorkTime = Calendar.getInstance();
            }
            if (wTaskPart.FinishWorkTime.compareTo(wBaseTime) <= 0) {
                wTaskPart.FinishWorkTime = Calendar.getInstance();
            }
            wTaskPart.Status = APSTaskStatus.Done.getValue();
            APSTaskPartDAO.getInstance().Update(BaseDAO.SysAdmin, wTaskPart, wErrorCode);
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    public ServiceResult<Integer> APS_UpdateTaskStep(BMSEmployee wLoginUser, APSTaskStep wAPSTaskStep) {
        ServiceResult<Integer> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            wResult.Result = APSTaskStepDAO.getInstance().Update(wLoginUser, wAPSTaskStep, wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(StringUtils.Format("{0} {1} ex：{2}",
                    "APSServiceImpl", "APS_UpdateTaskStep", e.toString()));
        }
        return wResult;
    }

    public ServiceResult<Integer> APS_ActiveTaskStepList(BMSEmployee wLoginUser, List<Integer> wIDList, int wActive) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            APSTaskStepDAO.getInstance().Active(wLoginUser, wIDList, wActive, wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(StringUtils.Format("{0} {1} ex：{2}",
                    "APSServiceImpl", "APS_ActiveTaskStepList", e.toString()));
        }
        return wResult;
    }

    /**
     * 查询历史排程结果
     */
    @Override
    public ServiceResult<List<APSTaskPart>> APS_QueryHistoryTaskPartList(BMSEmployee wLoginUser, int wAPSShiftPeriod,
                                                                         Calendar wStartTime, Calendar wEndTime) {
        ServiceResult<List<APSTaskPart>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            FMCShiftLevel wShiftLevel = MESServer.MES_QueryShiftLevel(wLoginUser, 0);
            int wShiftID = MESServer.MES_QueryShiftID(0, wStartTime, APSShiftPeriod.getEnumType(wAPSShiftPeriod),
                    wShiftLevel, 0);
            List<APSTaskPart> wList = APSTaskPartDAO.getInstance().SelectList(wLoginUser, -1, -1, -1, -1, -1, 1,
                    wAPSShiftPeriod, null, wShiftID, null, null, wErrorCode);
            if (wList == null || wList.size() <= 0)
                return wResult;
            APSTaskPart wMaxItem = wList.stream().max(Comparator.comparing(APSTaskPart::getSubmitTime)).get();
            Calendar wMaxSubmitTime = wMaxItem.SubmitTime;
            wList = wList.stream().filter(p -> p.SubmitTime.compareTo(wMaxSubmitTime) == 0)
                    .collect(Collectors.toList());
            wResult.Result = wList;
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(StringUtils.Format("{0} {1} ex：{2}", "APSServiceImpl", "APS_QueryHistoryTaskPartList",
                    e.toString()));
        }
        return wResult;
    }

    public ServiceResult<List<APSMessage>> APS_QueryMessageListBySubmitTime(BMSEmployee wLoginUser,
                                                                            Calendar wSubmitTime) {
        ServiceResult<List<APSMessage>> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            wResult.Result = APSMessageDAO.getInstance().SelectListBySubmitTime(wLoginUser, wSubmitTime, wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(StringUtils.Format("{0} {1} ex：{2}",
                    "APSServiceImpl", "APS_QueryMessageListBySubmitTime", e.toString()));
        }
        return wResult;
    }

    public ServiceResult<APSCondition> APS_QueryCondition(BMSEmployee wLoginUser, int wID) {
        ServiceResult<APSCondition> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            wResult.Result = APSConditionDAO.getInstance().SelectByID(wLoginUser, wID, wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(StringUtils.Format("{0} {1} ex：{2}",
                    "APSServiceImpl", "APS_QueryCondition", e.toString()));
        }
        return wResult;
    }

    public ServiceResult<List<APSCondition>> APS_QueryConditionList(BMSEmployee wLoginUser, int wID, int wShiftPeriod) {
        ServiceResult<List<APSCondition>> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            wResult.Result = APSConditionDAO.getInstance().SelectList(wLoginUser, wID, wShiftPeriod, wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(StringUtils.Format("{0} {1} ex：{2}",
                    "APSServiceImpl", "APS_QueryConditionList", e.toString()));
        }
        return wResult;
    }

    public ServiceResult<Integer> APS_UpdateCondition(BMSEmployee wLoginUser, APSCondition wAPSCondition) {
        ServiceResult<Integer> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            wResult.Result = APSConditionDAO.getInstance().Update(wLoginUser, wAPSCondition, wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(StringUtils.Format("{0} {1} ex：{2}",
                    "APSServiceImpl", "APS_UpdateCondition", e.toString()));
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<APSTaskStep>> APS_QueryTaskStepListByMonitorID(BMSEmployee wLoginUser, Calendar wTaskDate,
                                                                             int wMonitorID) {
        ServiceResult<List<APSTaskStep>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            // ①将wTaskDate转换为一天的开始时间和结束时间
            Calendar wStartTime = (Calendar) wTaskDate.clone();
            wStartTime.set(Calendar.HOUR_OF_DAY, 0);
            wStartTime.set(Calendar.MINUTE, 0);
            wStartTime.set(Calendar.SECOND, 0);
            Calendar wEndTime = (Calendar) wTaskDate.clone();
            wEndTime.set(Calendar.HOUR_OF_DAY, 23);
            wEndTime.set(Calendar.MINUTE, 59);
            wEndTime.set(Calendar.SECOND, 59);
            // ②获取登录者的工位列表
            List<Integer> wPartIDList = null;
            if (CoreServiceImpl.getInstance()
                    .BMS_CheckPowerByAuthorityID(wLoginUser.CompanyID, wLoginUser.ID, 501002, 0, 0)
                    .Info(Boolean.class)) {
                wPartIDList = new ArrayList<>();
            } else {
                // 工位ID集合
                wPartIDList = this.GetPartIDListByLoginUser(wLoginUser);
                if (wPartIDList == null || wPartIDList.size() <= 0) {
                    return wResult;
                }
            }
            // ③通过时间段和工位列表查询工位任务集合
            List<APSTaskPart> wTaskPartList = APSTaskPartDAO.getInstance().SelectListByTime(wLoginUser, wPartIDList,
                    wStartTime, wEndTime, wErrorCode);
            // ④通过工位任务集合查询工序任务集合
            if (wTaskPartList.size() > 0) {
                wResult.Result = APSTaskStepDAO.getInstance().SelectListByTaskPartIDList(wLoginUser,
                        wTaskPartList.stream().map(p -> p.ID).collect(Collectors.toList()), wErrorCode);
            }

            wResult.Result.removeIf(p -> p.Status == APSTaskStatus.Saved.getValue());

            // 终检任务、出厂检任务(未完成的，今日完成的)
            wResult.Result.addAll(APSTaskStepDAO.getInstance().SelectQTList(wLoginUser, null, null,
                    new ArrayList<>(
                            Arrays.asList(APSTaskStatus.Issued.getValue(), APSTaskStatus.Started.getValue())),
                    wPartIDList, wErrorCode));
            wResult.Result.addAll(APSTaskStepDAO.getInstance().SelectQTList(wLoginUser, wStartTime, wEndTime,
                    new ArrayList<>(Collections.singletonList(APSTaskStatus.Done.getValue())), wPartIDList,
                    wErrorCode));
            // 去重
            wResult.Result = new ArrayList<>(wResult.Result.stream()
                    .collect(Collectors.toMap(APSTaskStep::getID, account -> account, (k1, k2) -> k2)).values());

            if (wResult.Result.size() <= 0) {
                return wResult;
            }

            /*
             * 默认人员返回(没派工记录时默认返回)
             */
            Map<Integer, List<Integer>> wPersonMap = SFCServiceImpl.getInstance().SFC_QueryStepPersonMap(wLoginUser,
                    wResult.Result).Result;

            List<Integer> wAPSTaskstepIDList = wResult.Result.stream().map(p -> p.ID).collect(Collectors.toList());
            List<SFCTaskStep> wList = SFCTaskStepDAO.getInstance().SelectListByTaskStepIDList(wLoginUser,
                    wAPSTaskstepIDList, SFCTaskStepType.Step.getValue(), wErrorCode);

            for (APSTaskStep wAPSTaskStep : wResult.Result) {
                List<SFCTaskStep> wTempList = wList.stream().filter(p -> p.TaskStepID == wAPSTaskStep.ID)
                        .collect(Collectors.toList());

                if (wAPSTaskStep.OperatorList != null && wAPSTaskStep.OperatorList.size() > 0) {
                    wAPSTaskStep.Operators = GetUserNames(wAPSTaskStep.OperatorList);
                    continue;
                }

                if (wTempList.size() > 0) {
                    wAPSTaskStep.OperatorList = wTempList.stream().map(p -> p.OperatorID).collect(Collectors.toList());
                    continue;
                }

                if (!wPersonMap.containsKey(wAPSTaskStep.ID)) {
                    continue;
                }
                wAPSTaskStep.OperatorList = wPersonMap.get(wAPSTaskStep.ID);
                wAPSTaskStep.Operators = GetUserNames(wPersonMap.get(wAPSTaskStep.ID));
            }

            // ①获取工序中所有不在此班组的人员列表
            int wMonitorClassID = APSConstans.GetBMSEmployee(wMonitorID).DepartmentID;
            List<Integer> wNotInClassPersonIDList = new ArrayList<>();
            for (APSTaskStep wAPSTaskStep : wResult.Result) {
                if (wAPSTaskStep.IsDispatched) {
                    continue;
                }
                for (Integer wPersonID : wAPSTaskStep.OperatorList) {
                    if (APSConstans.GetBMSEmployee(wPersonID).DepartmentID != wMonitorClassID) {
                        if (wNotInClassPersonIDList.stream().noneMatch(p -> Objects.equals(p, wPersonID))) {
                            wNotInClassPersonIDList.add(wPersonID);
                        }
                    }
                }
            }
            // ②根据这些人员获取借调单列表
            List<SCHSecondmentApply> wSecondList = new ArrayList<>();
            if (wNotInClassPersonIDList.size() > 0) {
                wSecondList = SCHSecondmentApplyDAO.getInstance().SelectListByPersonIDList(wLoginUser,
                        wNotInClassPersonIDList, wErrorCode);
            }

            // ③判断此人是否有借调到本班组且未到期的借调单
            List<Integer> wNeedRemovePersonIDList = new ArrayList<>();
            for (Integer wPersonID : wNotInClassPersonIDList) {
                // ④若没有，加到需要移除的集合里
                if (wSecondList.stream()
                        .noneMatch(
                                p -> p.PersonID.contains(String.valueOf(wPersonID)) && p.NewClassID == wMonitorClassID
                                        && Calendar.getInstance().compareTo(p.StartTime) >= 0
                                        && Calendar.getInstance().compareTo(p.EndTime) <= 0)) {
                    wNeedRemovePersonIDList.add(wPersonID);
                }
            }
            // ⑤遍历工序列表，移除，未派工且在移除集合里的人
            for (APSTaskStep wAPSTaskStep : wResult.Result) {
                if (wAPSTaskStep.IsDispatched) {
                    continue;
                }

                if (wAPSTaskStep.OperatorList == null || wAPSTaskStep.OperatorList.size() <= 0) {
                    continue;
                }

                wAPSTaskStep.OperatorList
                        .removeIf(p -> wNeedRemovePersonIDList.stream().anyMatch(q -> Objects.equals(q, p)));
                wAPSTaskStep.Operators = GetUserNames(wAPSTaskStep.OperatorList);
            }
        } catch (Exception e) {
            logger.error(StringUtils.Format("{0} {1} ex：{2}", "APSServiceImpl", "APS_QueryTaskStepListByMonitorID",
                    e.toString()));
        }
        return wResult;
    }

    private String GetUserNames(List<Integer> wList) {
        String wResult = "";
        try {
            if (wList == null || wList.size() <= 0) {
                return wResult;
            }

            List<String> wNameList = new ArrayList<>();

            for (Integer wUserID : wList) {
                String wTemp = APSConstans.GetBMSEmployeeName(wUserID);
                if (StringUtils.isNotEmpty(wTemp)) {
                    wNameList.add(wTemp);
                }
            }

            if (wNameList.size() > 0) {
                wResult = StringUtils.Join(",", wNameList);
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
        return wResult;
    }

    /**
     * 获取登录者所管辖的工位列表
     */
    private List<Integer> GetPartIDListByLoginUser(BMSEmployee wLoginUser) {
        List<Integer> wResult = new ArrayList<>();
        try {
            // 判断此人是否是班组长
            if (APSConstans.GetBMSDepartment(wLoginUser.DepartmentID).Type != BMSDepartmentType.Class.getValue()
                    || APSConstans.GetBMSPosition(wLoginUser.Position).DutyID != 1) {
                return wResult;
            }

            int wClassID = wLoginUser.DepartmentID;

            // 班组工位列表
            List<FMCWorkCharge> wList1 = CoreServiceImpl.getInstance().FMC_QueryWorkChargeList(wLoginUser)
                    .List(FMCWorkCharge.class);
            if (wList1 == null) {
                return wResult;
            }

            wList1 = wList1.stream().filter(p -> p.ClassID == wClassID && p.Active == 1).collect(Collectors.toList());

            wResult = wList1.stream().map(p -> p.StationID).collect(Collectors.toList());
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<APSSchedulingVersion>> APS_QueryAuditTaskList(BMSEmployee wLoginUser, int wAPSShiftPeriod,
                                                                            Calendar wShiftDate, int wTagType) {
        ServiceResult<List<APSSchedulingVersion>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            List<APSSchedulingVersion> wSchedulingList = APSSchedulingVersionDAO.getInstance().SelectList(wLoginUser,
                    -1, wAPSShiftPeriod, null,
                    new ArrayList<>(
                            Arrays.asList(APSTaskStatus.Saved.getValue(), APSTaskStatus.Submit.getValue(),
                                    APSTaskStatus.ToAudit.getValue(), APSTaskStatus.Audited.getValue())),
                    wErrorCode);

            int wModuleID = 0;
            switch (APSShiftPeriod.getEnumType(wAPSShiftPeriod)) {
                case Month:
                    wModuleID = BPMEventModule.SCMonthAudit.getValue();
                    break;
                case Week:
                    wModuleID = BPMEventModule.SCWeekAudit.getValue();
                    break;
                default:
                    break;
            }

            int wShiftID = MESServer.MES_QueryShiftID(wLoginUser.CompanyID, wShiftDate, APSShiftPeriod.Day,
                    FMCShiftLevel.Day, 0);

            List<BFCMessage> wMessageList = null;
            switch (TagTypes.getEnumType(wTagType)) {
                case Dispatcher:// 待办
                    // 待提交的任务列表
                    if (CoreServiceImpl.getInstance().BMS_CheckPowerByAuthorityID(wLoginUser.CompanyID, wLoginUser.ID,
                            MBSRoleTree.PlanSubmit.getValue(), 0, 0).Info(Boolean.class)) {
                        wResult.Result.addAll(wSchedulingList.stream()
                                .filter(p -> p.Status == APSTaskStatus.Saved.getValue()).collect(Collectors.toList()));
                    }
                    // 若是已提交的任务，则根据当前登录者的权限和审批配置判断该任务此人是否有权限拿
                    int wModuleTempID = wModuleID;
                    for (APSSchedulingVersion wAPSSchedulingVersion : wSchedulingList) {
                        wMessageList = CoreServiceImpl.getInstance().BFC_GetMessageList(wLoginUser, wLoginUser.ID,
                                        wModuleID, BFCMessageType.Task.getValue(), 0, wShiftID, null, null)
                                .List(BFCMessage.class);
                        if (wMessageList != null && wMessageList.size() > 0
                                && wMessageList.stream().anyMatch(p -> p.Active == 0 && p.ModuleID == wModuleTempID
                                && p.MessageID == wAPSSchedulingVersion.ID)) {
                            wResult.Result.add(wAPSSchedulingVersion);
                        }
                    }
                    break;
                case Applicant:// 已办
                    List<BFCAuditAction> wActionList = null;
                    for (APSSchedulingVersion wAPSSchedulingVersion : wSchedulingList) {
                        wActionList = CoreServiceImpl.getInstance()
                                .BFC_ActionAll(wLoginUser, wModuleID, wAPSSchedulingVersion.ID)
                                .List(BFCAuditAction.class);
                        if (wActionList != null && wActionList.size() > 0
                                && wActionList.stream().anyMatch(p -> p.AuditorID == wLoginUser.ID)) {
                            wResult.Result.add(wAPSSchedulingVersion);
                        }
                    }
                    break;
                default:
                    break;
            }
            // 去重
            if (wResult.Result != null && wResult.Result.size() > 0) {
                wResult.Result = new ArrayList<>(wResult.Result.stream()
                        .collect(Collectors.toMap(APSSchedulingVersion::getID, account -> account, (k1, k2) -> k2))
                        .values());
                for (APSSchedulingVersion wAPSSchedulingVersion : wResult.Result) {
                    wAPSSchedulingVersion.APSTaskPartList = APSTaskPartDAO.getInstance().SelectListByIDList(wLoginUser,
                            wAPSSchedulingVersion.TaskPartIDList, wErrorCode);
                }
            }
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(
                    StringUtils.Format("{0} {1} ex：{2}", "APSServiceImpl", "APS_QueryAuditTaskList", e.toString()));
        }
        return wResult;
    }

    @Override
    public synchronized ServiceResult<Integer> APS_AuditOperate(BMSEmployee wLoginUser,
                                                                APSSchedulingVersion wAPSSchedulingVersion,
                                                                int wOperateType, int wAPSShiftPeriod) {
        ServiceResult<Integer> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            if (wLoginUser.getID() < 0 && wLoginUser.getID() != BaseDAO.SysAdmin.ID) {
                wResult.FaultCode += "用户不存在";
                return wResult;
            }

            switch (APSOperateType.getEnumType(wOperateType)) {
                case Submit:// 提交
                case Audit:// 审批
                case Reject:// 驳回
                    // 更新任务状态
                    APSSchedulingVersionDAO.getInstance().Audit(wLoginUser, wAPSSchedulingVersion, wOperateType,
                            wErrorCode);
                    if (wErrorCode.Result != 0) {
                        wResult.FaultCode += MESException.getEnumType(wErrorCode.Result).getLable();
                        return wResult;
                    }
                    APSTaskPartDAO.getInstance().Update(wLoginUser, wAPSSchedulingVersion.TaskPartIDList,
                            wAPSSchedulingVersion.Status, wErrorCode);
                    break;
                case Issued:// 下达
                    int wFunctionID = 0;
                    switch (APSShiftPeriod.getEnumType(wAPSShiftPeriod)) {
                        case Month:
                            wFunctionID = 82000001;
                            break;
                        case Week:
                            wFunctionID = 82000002;
                            break;
                        default:
                            break;
                    }
                    // 【周排程】权限控制
                    if (!CoreServiceImpl.getInstance()
                            .BMS_CheckPowerByAuthorityID(wLoginUser.CompanyID, wLoginUser.ID, wFunctionID, 0, 0)
                            .Info(Boolean.class)) {
                        wResult.FaultCode += RetCode.SERVER_CODE_UNROLE;
                        return wResult;
                    }
                    if (wAPSSchedulingVersion.APSTaskPartList.stream()
                            .anyMatch(p -> p.Status != APSTaskStatus.Audited.getValue())) {
                        wResult.FaultCode = StringUtils.Format("提示：无法下达状态为【{0}】的周计划",
                                APSTaskStatus.getEnumType(wAPSSchedulingVersion.APSTaskPartList.get(0).Status)
                                        .getLable());
                        return wResult;
                    }

                    wAPSSchedulingVersion.Status = APSTaskStatus.Issued.getValue();
                    APSSchedulingVersionDAO.getInstance().Update(wLoginUser, wAPSSchedulingVersion, wErrorCode);
                    APSTaskPartDAO.getInstance().Update(wLoginUser, wAPSSchedulingVersion.TaskPartIDList,
                            wAPSSchedulingVersion.Status, wErrorCode);

                    if (wAPSShiftPeriod == APSShiftPeriod.Week.getValue()) {
                        ExecutorService wES = Executors.newFixedThreadPool(1);
                        wES.submit(() -> APS_TriggerDayPlans(wLoginUser, wAPSSchedulingVersion));
                        wES.shutdown();
                    }
                    break;
                default:
                    break;
            }
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode = e.toString();
            logger.error(StringUtils.Format("{0} {1} ex：{2}", "APSServiceImpl", "APS_AuditOperate", e.toString()));
        }
        return wResult;
    }

    /**
     * 制定所有的日计划
     */
    private void MakingAllTaskStep(BMSEmployee wLoginUser, APSSchedulingVersion wAPSSchedulingVersion) {
        try {
            if (wAPSSchedulingVersion == null || wAPSSchedulingVersion.APSTaskPartList == null
                    || wAPSSchedulingVersion.APSTaskPartList.size() <= 0) {
                return;
            }

            OutResult<Integer> wErrorCode = new OutResult<>(0);

            // ①获取所有工位任务
            List<APSTaskPart> wTaskPartList = APSTaskPartDAO.getInstance().SelectListByIDList(wLoginUser,
                    wAPSSchedulingVersion.TaskPartIDList, wErrorCode);
            if (wTaskPartList == null || wTaskPartList.size() <= 0) {
                return;
            }
            // ②获取所有订单
            List<OMSOrder> wOrderList = OMSOrderDAO.getInstance().SelectListByIDList(wLoginUser,
                    wTaskPartList.stream().map(p -> p.OrderID).distinct().collect(Collectors.toList()), wErrorCode);
            if (wOrderList == null || wOrderList.size() <= 0) {
                return;
            }
            // ①根据订单ID集合获取工序计划集合
            List<APSTaskStepPlan> wStepPlanList = APSTaskStepPlanDAO.getInstance().SelectList(wLoginUser,
                    wOrderList.stream().map(p -> p.ID).distinct().collect(Collectors.toList()), wErrorCode);
            // ③遍历工位任务，获取工艺工序数据
            Calendar wBaseTime = Calendar.getInstance();
            wBaseTime.set(2000, 0, 1);
            int wShiftID = MESServer.MES_QueryShiftID(wLoginUser.CompanyID, Calendar.getInstance(), APSShiftPeriod.Day,
                    FMCShiftLevel.Day, 0);
            for (APSTaskPart wAPSTaskPart : wTaskPartList) {
                if (wOrderList.stream().noneMatch(p -> p.ID == wAPSTaskPart.OrderID)) {
                    continue;
                }

                OMSOrder wOrder = wOrderList.stream().filter(p -> p.ID == wAPSTaskPart.OrderID).findFirst().get();

                List<FPCRoutePartPoint> wRoutePartPointList = FMCServiceImpl.getInstance()
                        .FPC_QueryRoutePartPointListByRouteID(wLoginUser, wOrder.RouteID, wAPSTaskPart.PartID)
                        .List(FPCRoutePartPoint.class);

                if (wRoutePartPointList == null || wRoutePartPointList.size() <= 0) {
                    continue;
                }

                // 是否过滤制造目标的工序计划生成
                boolean wIsFilterMakingTarget = Configuration.readConfigString("IsFilterMakingTarget", "config/config")
                        .equals("1");

                // ④遍历工艺工序数据，判断是否存在日计划，若存在修改，否则新增
                APSTaskStep wAPSTaskStep = null;

                // 查询工序周计划
                List<APSPartPointWeekPlan> wApsPartPointWeekPlans = APSPartPointWeekPlanDAO.getInstance().SelectList(
                        wLoginUser, -1, wAPSTaskPart.OrderID,
                        wAPSTaskPart.PartID, -1, wErrorCode);

                for (FPCRoutePartPoint wFPCRoutePartPoint : wRoutePartPointList) {
                    // 工序周计划未排的过滤
                    if (wApsPartPointWeekPlans != null && wApsPartPointWeekPlans.size() > 0
                            && wApsPartPointWeekPlans.stream()
                            .noneMatch(p -> p.PartPointID == wFPCRoutePartPoint.PartPointID)) {
                        continue;
                    }

                    List<APSTaskStep> wList = APSTaskStepDAO.getInstance().SelectList(wLoginUser, -1, wOrder.ID, -1, -1,
                            -1, -1, wAPSTaskPart.PartID, wFPCRoutePartPoint.PartPointID, -1, -1, null, null, null, null,
                            wErrorCode);
                    if (wList != null && wList.size() > 0) {
                        wAPSTaskStep = wList.get(0);
                        wAPSTaskStep.TaskPartID = wAPSTaskPart.ID;
                        wAPSTaskStep.Active = 1;
                        if (wStepPlanList.stream().anyMatch(p -> p.OrderID == wAPSTaskPart.OrderID
                                && p.PartID == wAPSTaskPart.PartID && p.StepID == wFPCRoutePartPoint.PartPointID)) {
                            APSTaskStepPlan wStepPlan = wStepPlanList.stream()
                                    .filter(p -> p.OrderID == wAPSTaskPart.OrderID && p.PartID == wAPSTaskPart.PartID
                                            && p.StepID == wFPCRoutePartPoint.PartPointID)
                                    .findFirst().get();
                            wAPSTaskStep.PlanStartTime = wStepPlan.StartTime;
                            wAPSTaskStep.PlanEndTime = wStepPlan.EndTime;
                        } else {
                            wAPSTaskStep.PlanStartTime = wAPSTaskPart.StartTime;
                            wAPSTaskStep.PlanEndTime = wAPSTaskPart.EndTime;
                        }

                        wAPSTaskStep.ReadyTime = Calendar.getInstance();

                        wAPSTaskStep.ShiftID = wShiftID;

                    } else {
                        wAPSTaskStep = new APSTaskStep();

                        // 若过滤制造目标且制造目标不为空
                        if (wIsFilterMakingTarget && StringUtils.isNotEmpty(wFPCRoutePartPoint.MaterialNo_S)) {
                            continue;
                        }

                        wAPSTaskStep.Active = 1;
                        wAPSTaskStep.ID = 0;
                        wAPSTaskStep.LineID = wAPSTaskPart.LineID;
                        wAPSTaskStep.MaterialNo = wAPSTaskPart.MaterialNo;
                        wAPSTaskStep.OrderID = wAPSTaskPart.OrderID;
                        wAPSTaskStep.PartID = wAPSTaskPart.PartID;
                        wAPSTaskStep.PartNo = wAPSTaskPart.PartNo;
                        wAPSTaskStep.PlanerID = wLoginUser.ID;
                        wAPSTaskStep.ProductNo = wAPSTaskPart.ProductNo;
                        wAPSTaskStep.ShiftID = wShiftID;
                        wAPSTaskStep.Status = APSTaskStatus.Saved.getValue();
                        wAPSTaskStep.StepID = wFPCRoutePartPoint.PartPointID;
                        wAPSTaskStep.TaskPartID = wAPSTaskPart.ID;
                        wAPSTaskStep.TaskLineID = wAPSTaskPart.TaskLineID;
                        wAPSTaskStep.TaskText = wAPSTaskPart.TaskText;
                        wAPSTaskStep.WorkHour = 0;
                        wAPSTaskStep.WorkShopID = wAPSTaskPart.WorkShopID;
                        wAPSTaskStep.StartTime = wBaseTime;
                        wAPSTaskStep.EndTime = wBaseTime;
                        wAPSTaskStep.ReadyTime = wBaseTime;
                        wAPSTaskStep.CreateTime = Calendar.getInstance();
                        wAPSTaskStep.PartPointType = wFPCRoutePartPoint.PartPointType;
                        wAPSTaskStep.FQTY = wFPCRoutePartPoint.TargetNum;
                        wAPSTaskStep.MaterialNoNew = wFPCRoutePartPoint.MaterialNo;

                        if (wStepPlanList.stream().anyMatch(p -> p.OrderID == wAPSTaskPart.OrderID
                                && p.PartID == wAPSTaskPart.PartID && p.StepID == wFPCRoutePartPoint.PartPointID)) {
                            APSTaskStepPlan wStepPlan = wStepPlanList.stream()
                                    .filter(p -> p.OrderID == wAPSTaskPart.OrderID && p.PartID == wAPSTaskPart.PartID
                                            && p.StepID == wFPCRoutePartPoint.PartPointID)
                                    .findFirst().get();
                            wAPSTaskStep.PlanStartTime = wStepPlan.StartTime;
                            wAPSTaskStep.PlanEndTime = wStepPlan.EndTime;
                        } else {
                            wAPSTaskStep.PlanStartTime = wAPSTaskPart.StartTime;
                            wAPSTaskStep.PlanEndTime = wAPSTaskPart.EndTime;
                        }
                    }

                    APSTaskStepDAO.getInstance().Update(wLoginUser, wAPSTaskStep, wErrorCode);
                }
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    /**
     * 触发质量日计划
     */
    private void TriggerQualityDayPlans(BMSEmployee wLoginUser, APSSchedulingVersion wAPSSchedulingVersion) {
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            if (wAPSSchedulingVersion.APSTaskPartList == null || wAPSSchedulingVersion.APSTaskPartList.size() <= 0) {
                return;
            }

            List<FPCPart> wQPartList = FMCServiceImpl.getInstance()
                    .FPC_QueryPartList(wLoginUser, -1, -1, -1, FPCPartTypes.QTFinally.getValue()).List(FPCPart.class);
            if (wQPartList == null || wQPartList.size() <= 0) {
                return;
            }

            for (APSTaskPart wAPSTaskPart : wAPSSchedulingVersion.APSTaskPartList) {
                List<FPCPart> wTempPartList = wQPartList.stream()
                        .filter(p -> (p.QTPartID == wAPSTaskPart.PartID)).collect(Collectors.toList());
                if (wTempPartList.size() <= 0) {
                    continue;
                }

                OMSOrder wOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wAPSTaskPart.OrderID, wErrorCode);
                if (wOrder == null || wOrder.ID <= 0) {
                    continue;
                }
                for (FPCPart wFPCPart : wTempPartList) {
                    List<Integer> wStepIDList = APSUtils.getInstance().FMC_QueryStepIDList(wLoginUser, wOrder.LineID,
                            wFPCPart.ID, wOrder.ProductID);
                    if (wStepIDList == null || wStepIDList.size() <= 0) {
                        continue;
                    }

                    List<APSTaskStep> wList = APSTaskStepDAO.getInstance().SelectList(wLoginUser, -1, wOrder.ID, -1, -1,
                            -1, -1, wFPCPart.ID, -1, -1, 1, null, null, null, null, wErrorCode);
                    if (wList != null && wList.size() > 0) {
                        continue;
                    }

                    CreateQualityDayPlans(wLoginUser, wStepIDList, wFPCPart, wOrder);
                }
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    private void CreateQualityDayPlans(BMSEmployee wAdminUser, List<Integer> wStepIDList, FPCPart wFPCPart,
                                       OMSOrder wOrder) {
        OutResult<Integer> wErrorCode = new OutResult<>(0);

        try {
            int wShiftID = MESServer.MES_QueryShiftID(wAdminUser.CompanyID, Calendar.getInstance(), APSShiftPeriod.Day,
                    FMCShiftLevel.Day, 0);

            for (Integer wStepID : wStepIDList) {
                APSTaskStep wAPSTaskStep = new APSTaskStep();

                wAPSTaskStep.ID = 0;
                wAPSTaskStep.Active = 1;
                wAPSTaskStep.CreateTime = Calendar.getInstance();
                wAPSTaskStep.LineID = wOrder.LineID;
                wAPSTaskStep.OrderID = wOrder.ID;
                wAPSTaskStep.PartID = wFPCPart.ID;
                wAPSTaskStep.ProductNo = wOrder.ProductNo;
                wAPSTaskStep.ShiftID = wShiftID;
                wAPSTaskStep.Status = APSTaskStatus.Issued.getValue();
                wAPSTaskStep.StepID = wStepID;
                wAPSTaskStep.IsDispatched = false;
                wAPSTaskStep.PartNo = wOrder.PartNo;
                wAPSTaskStep.ReadyTime = Calendar.getInstance();

                int wNewID = APSTaskStepDAO.getInstance().Update(wAdminUser, wAPSTaskStep, wErrorCode);
                if (wNewID <= 0) {
                    break;
                }
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    public ServiceResult<APSAuditConfig> APS_QueryAuditConfig(BMSEmployee wLoginUser, int wID) {
        ServiceResult<APSAuditConfig> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            wResult.Result = APSAuditConfigDAO.getInstance().SelectByID(wLoginUser, wID, wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(StringUtils.Format("{0} {1} ex：{2}",
                    "APSServiceImpl", "APS_QueryAuditConfig", e.toString()));
        }
        return wResult;
    }

    public ServiceResult<List<APSAuditConfig>> APS_QueryAuditConfigList(BMSEmployee wLoginUser, int wID,
                                                                        int wAPSShiftPeriod) {
        ServiceResult<List<APSAuditConfig>> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            wResult.Result = APSAuditConfigDAO.getInstance().SelectList(wLoginUser, wID, wAPSShiftPeriod, wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(StringUtils.Format("{0} {1} ex：{2}",
                    "APSServiceImpl", "APS_QueryAuditConfigList", e.toString()));
        }
        return wResult;
    }

    public ServiceResult<Integer> APS_UpdateAuditConfig(BMSEmployee wLoginUser, APSAuditConfig wAPSAuditConfig) {
        ServiceResult<Integer> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            wResult.Result = APSAuditConfigDAO.getInstance().Update(wLoginUser, wAPSAuditConfig, wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(StringUtils.Format("{0} {1} ex：{2}",
                    "APSServiceImpl", "APS_UpdateAuditConfig", e.toString()));
        }
        return wResult;
    }

    public ServiceResult<Integer> APS_DeleteAuditConfigList(BMSEmployee wLoginUser,
                                                            List<APSAuditConfig> wAPSAuditConfigList) {
        ServiceResult<Integer> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            wResult = APSAuditConfigDAO.getInstance().DeleteList(wLoginUser, wAPSAuditConfigList, wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(StringUtils.Format("{0} {1} ex：{2}",
                    "APSServiceImpl", "APS_DeleteAuditConfigList", e.toString()));
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<FPCProduct>> APS_PlanProductList(BMSEmployee wLoginUser, int wShiftPeriod) {
        ServiceResult<List<FPCProduct>> wResult = new ServiceResult<>();
        try {
            wResult.Result = new ArrayList<>();
            ServiceResult<List<APSTaskPart>> wRst = APS_QueryHistoryTaskPartList(wLoginUser, wShiftPeriod,
                    Calendar.getInstance(), null);
            if (wRst == null || wRst.Result == null || wRst.Result.size() <= 0)
                return wResult;

            // 产品型号映射
            Map<String, FPCProduct> wProductMap = MyHelperServiceImpl.getInstance()
                    .FPC_QueryProductNameMap(wLoginUser).Result;
            if (wProductMap == null || wProductMap.size() <= 0)
                return wResult;

            for (APSTaskPart wAPSTaskPart : wRst.Result) {
                String[] wCars = wAPSTaskPart.PartNo.split("#");
                if (wCars.length != 2)
                    continue;
                if (wProductMap.containsKey(wCars[0]))
                    wResult.Result.add(wProductMap.get(wCars[0]));
            }

            // 去重
            if (wResult.Result.size() > 0) {
                wResult.Result = new ArrayList<>(wResult.Result.stream()
                        .collect(Collectors.toMap(FPCProduct::getID, account -> account, (k1, k2) -> k2)).values());
            }
        } catch (Exception e) {
            logger.error(StringUtils.Format("{0} {1} ex：{2}", "APSServiceImpl", "APS_PlanProductList", e.toString()));
        }
        return wResult;
    }

    public ServiceResult<Integer> APS_AdjustHour(BMSEmployee wLoginUser, List<APSTaskStep> wAPSTaskStepList,
                                                 double wHour) {
        ServiceResult<Integer> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            for (APSTaskStep wAPSTaskStep : wAPSTaskStepList) {
                wAPSTaskStep.WorkHour = wHour;
                APSTaskStepDAO.getInstance().Update(wLoginUser, wAPSTaskStep, wErrorCode);
            }
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode = wResult.FaultCode + e;
            logger.error(StringUtils.Format("{0} {1} ex：{2}",
                    "APSServiceImpl", "APS_AdjustHour", e.toString()));
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<APSTaskStep>> APS_QueryAuditStepTaskList(BMSEmployee wLoginUser, int wTagType,
                                                                       Calendar wShiftDate) {
        ServiceResult<List<APSTaskStep>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            int wModuleID = BPMEventModule.SCDayAudit.getValue();

            int wShiftID = MESServer.MES_QueryShiftID(wLoginUser.CompanyID, wShiftDate, APSShiftPeriod.Day,
                    FMCShiftLevel.Default, 0);

            List<APSTaskStep> wHisTaskList = APSTaskStepDAO.getInstance().SelectList(wLoginUser, -1, -1, -1, -1, -1, -1,
                    -1, -1, -1, 1,
                    new ArrayList<>(Arrays.asList(APSTaskStatus.Saved.getValue(),
                            APSTaskStatus.ToAudit.getValue(), APSTaskStatus.Audited.getValue())),
                    null, null, null, wErrorCode);

            List<BFCMessage> wMessageList = null;
            switch (TagTypes.getEnumType(wTagType)) {
                case Dispatcher:// 待办
                    // 若是已提交的任务，则根据当前登录者的权限和审批配置判断该任务此人是否有权限拿
                    for (APSTaskStep wAPSTaskStep : wHisTaskList) {
                        wMessageList = CoreServiceImpl.getInstance().BFC_GetMessageList(wLoginUser, wLoginUser.ID,
                                        wModuleID, BFCMessageType.Task.getValue(), 0, wShiftID, null, null)
                                .List(BFCMessage.class);
                        if (wMessageList != null && wMessageList.size() > 0
                                && wMessageList.stream().anyMatch(p -> p.MessageID == wAPSTaskStep.ID)) {
                            wResult.Result.add(wAPSTaskStep);
                        }
                    }
                    break;
                case Applicant:// 已办
                    List<BFCAuditAction> wActionList = null;
                    for (APSTaskStep wAPSTaskStep : wHisTaskList) {
                        wActionList = CoreServiceImpl.getInstance().BFC_ActionAll(wLoginUser, wModuleID,
                                        wAPSTaskStep.ID)
                                .List(BFCAuditAction.class);
                        if (wActionList != null && wActionList.size() > 0
                                && wActionList.stream().anyMatch(p -> p.AuditorID == wLoginUser.ID)) {
                            wResult.Result.add(wAPSTaskStep);
                        }
                    }
                    break;
                default:
                    break;
            }
            // 去重
            if (wResult.Result != null && wResult.Result.size() > 0) {
                wResult.Result = new ArrayList<>(wResult.Result.stream()
                        .collect(Collectors.toMap(APSTaskStep::getID, account -> account, (k1, k2) -> k2)).values());
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(
                    StringUtils.Format("{0} {1} ex：{2}", "APSServiceImpl", "APS_QueryAuditStepTaskList", e.toString()));
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> APS_AuditStepOperate(BMSEmployee wLoginUser, List<APSTaskStep> wTaskList,
                                                       int wOperateType) {
        ServiceResult<Integer> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            int wShiftID = MESServer.MES_QueryShiftID(wLoginUser.CompanyID, Calendar.getInstance(), APSShiftPeriod.Day,
                    FMCShiftLevel.Day, 0);

            List<Integer> wPartIDList = null;
            Map<Integer, List<Integer>> wAreaPartIDMap = null;
            switch (APSOperateType.getEnumType(wOperateType)) {
                case Submit:
                    if (wTaskList.stream().anyMatch(p -> p.Status == APSTaskStatus.Saved.getValue()
                            && (p.Remark == null || StringUtils.isEmpty(p.Remark.Remark)))) {
                        wResult.FaultCode += "提示：未提交的计划需要填写备注!";
                        return wResult;
                    }

                    // 保存备注
                    SaveRemarks(wLoginUser, wTaskList);

                    List<APSTaskStep> wAuditList = wTaskList.stream()
                            .filter(p -> p.Status == APSTaskStatus.Submit.getValue()).collect(Collectors.toList());

                    if (wAuditList.size() <= 0) {
                        wResult.FaultCode += "提示：提交的数据中必须包含要审批的数据!";
                        return wResult;
                    }

                    // 获取工区
                    Optional<LFSWorkAreaStation> wOption = APSConstans.GetLFSWorkAreaStationList().values().stream()
                            .filter(p -> p.StationID == wAuditList.get(0).PartID).findFirst();
                    if (!wOption.isPresent() || wOption.get().WorkAreaID <= 0) {
                        wResult.FaultCode += "提示：工区未找到!";
                        return wResult;
                    }
                    int wAreaID = wOption.get().WorkAreaID;
                    // 根据工区和ShiftID查询日计划审批数据
                    Calendar wBaseTime = Calendar.getInstance();
                    wBaseTime.set(2000, 0, 1);
                    List<APSDayPlanAudit> wDayAuditList = APSDayPlanAuditDAO.getInstance().SelectList(wLoginUser, -1,
                            wAreaID, wShiftID, null, wErrorCode);
                    if (wDayAuditList == null || wDayAuditList.size() <= 0) {
                        // 关闭过期的审批单
                        APSDayPlanAuditDAO.getInstance().CloseAreaAudit(wLoginUser, wAreaID, wErrorCode);
                        // 创建新的审批单
                        APSDayPlanAudit wAPSDayPlanAudit = new APSDayPlanAudit(0, wAreaID, "", wShiftID,
                                wLoginUser.ID, "",
                                Calendar.getInstance(), 0, "", wBaseTime, BPMStatus.Save.getValue());
                        wAPSDayPlanAudit.ID = APSDayPlanAuditDAO.getInstance().Update(wLoginUser, wAPSDayPlanAudit,
                                wErrorCode);
                        APSDayPlanAuditDAO.getInstance().Audit(wLoginUser, wAPSDayPlanAudit, wOperateType, wErrorCode);
                        if (wErrorCode.Result == 0) {
                            for (APSTaskStep wAPSTaskStep : wAuditList) {
                                wAPSTaskStep.ShiftID = wShiftID;
                                wAPSTaskStep.Status = APSTaskStatus.ToAudit.getValue();
                                APSTaskStepDAO.getInstance().Update(wLoginUser, wAPSTaskStep, wErrorCode);
                            }
                        }
                    } else if (wDayAuditList.stream().anyMatch(p -> p.Status == BPMStatus.Save.getValue())) {
                        APSDayPlanAudit wAPSDayPlanAudit = wDayAuditList.stream()
                                .filter(p -> p.Status == BPMStatus.Save.getValue()).findFirst().get();
                        APSDayPlanAuditDAO.getInstance().Audit(wLoginUser, wAPSDayPlanAudit, wOperateType, wErrorCode);
                        if (wErrorCode.Result == 0) {
                            for (APSTaskStep wAPSTaskStep : wAuditList) {
                                wAPSTaskStep.ShiftID = wShiftID;
                                wAPSTaskStep.Status = APSTaskStatus.ToAudit.getValue();
                                APSTaskStepDAO.getInstance().Update(wLoginUser, wAPSTaskStep, wErrorCode);
                            }
                        }
                    }
                    // else if (wDayAuditList.stream().anyMatch(
                    // p -> p.Status != BPMStatus.Audited.getValue() && p.Status !=
                    // BPMStatus.Save.getValue())) {
                    // wResult.FaultCode += "提示：本工区今日日计划已制定，请审批完成后再试!";
                    // return wResult;
                    // }

                    else {
                        String wReSubmitStr = Configuration.readConfigString("resubmit", "config/config");
                        int wReSubmit = Integer.parseInt(wReSubmitStr);
                        if (wReSubmit != 1) {
                            wResult.FaultCode += "提示：本工区今日日计划已制定，无法再次制定!";
                            return wResult;
                        }
                        // 重新制定日计划
                        APSDayPlanAudit wAPSDayPlanAudit = new APSDayPlanAudit(0, wAreaID, "", wShiftID,
                                wLoginUser.ID, "",
                                Calendar.getInstance(), 0, "", wBaseTime, BPMStatus.Save.getValue());
                        wAPSDayPlanAudit.ID = APSDayPlanAuditDAO.getInstance().Update(wLoginUser, wAPSDayPlanAudit,
                                wErrorCode);
                        APSDayPlanAuditDAO.getInstance().Audit(wLoginUser, wAPSDayPlanAudit, wOperateType, wErrorCode);
                        if (wErrorCode.Result == 0) {
                            for (APSTaskStep wAPSTaskStep : wAuditList) {
                                wAPSTaskStep.Status = APSTaskStatus.ToAudit.getValue();
                                wAPSTaskStep.ShiftID = wShiftID;
                                APSTaskStepDAO.getInstance().Update(wLoginUser, wAPSTaskStep, wErrorCode);
                            }
                        }
                    }

                    // 将工位计划状态改为“已确认”
                    List<Integer> wTaskPartIDList = wAuditList.stream()
                            .filter(p -> p.Status == APSTaskStatus.ToAudit.getValue()).map(p -> p.TaskPartID).distinct()
                            .collect(Collectors.toList());
                    if (wTaskPartIDList.size() > 0) {
                        List<APSTaskPart> wTaskPartList = APSTaskPartDAO.getInstance().SelectListByIDList(wLoginUser,
                                wTaskPartIDList, wErrorCode);
                        for (APSTaskPart wAPSTaskPart : wTaskPartList) {
                            wAPSTaskPart.Status = APSTaskStatus.Confirm.getValue();
                            APSTaskPartDAO.getInstance().Update(wLoginUser, wAPSTaskPart, wErrorCode);
                        }
                    }
                    break;
                case Audit:
                    wPartIDList = wTaskList.stream().map(p -> p.PartID).distinct().collect(Collectors.toList());

                    wAreaPartIDMap = new HashMap<>();
                    for (Integer wPartID : wPartIDList) {
                        int wID = GetAreaIDByPartID(wPartID);
                        if (wID > 0) {
                            if (wAreaPartIDMap.containsKey(wID)) {
                                List<Integer> wIDList = wAreaPartIDMap.get(wID);
                                if (wIDList.stream().noneMatch(p -> p.equals(wPartID))) {
                                    wIDList.add(wPartID);
                                }
                            } else {
                                List<Integer> wIDList = new ArrayList<>();
                                wIDList.add(wPartID);
                                wAreaPartIDMap.put(wID, wIDList);
                            }
                        }
                    }

                    // 遍历工区映射，审批日计划
                    for (Integer wAreaItemID : wAreaPartIDMap.keySet()) {
                        // 查找日计划配置
                        List<APSDayPlanAudit> wDayPlanAuditList = APSDayPlanAuditDAO.getInstance().SelectList(
                                wLoginUser,
                                -1, wAreaItemID, -1,
                                new ArrayList<>(Collections.singletonList(BPMStatus.ToAudit.getValue())),
                                wErrorCode);
                        if (wDayPlanAuditList == null || wDayPlanAuditList.size() <= 0) {
                            continue;
                        }
                        APSDayPlanAudit wAPSDayPlanAudit = wDayPlanAuditList.get(wDayPlanAuditList.size() - 1);
                        APSDayPlanAuditDAO.getInstance().Audit(wLoginUser, wAPSDayPlanAudit, wOperateType, wErrorCode);
                        if (wAPSDayPlanAudit.Status == BPMStatus.Audited.getValue()) {
                            Map<Integer, List<Integer>> wTempMap = wAreaPartIDMap;
                            // 查找工序任务
                            List<APSTaskStep> wStepTaskList = wTaskList.stream()
                                    .filter(p -> wTempMap.get(wAreaItemID).stream().anyMatch(q -> q == p.PartID))
                                    .collect(Collectors.toList());
                            // 修改工序任务状态
                            wStepTaskList.forEach(p -> p.Status = APSTaskStatus.Audited.getValue());
                            for (APSTaskStep wAPSTaskStep : wStepTaskList) {
                                APSTaskStepDAO.getInstance().Update(wLoginUser, wAPSTaskStep, wErrorCode);
                            }
                            // 关闭待审批的消息
                            CloseMessage(wLoginUser, wAPSDayPlanAudit.ID);
                        }
                    }
                    break;
                case Cancel:// 撤回
                case Reject:// 驳回
                    wPartIDList = wTaskList.stream().map(p -> p.PartID).distinct().collect(Collectors.toList());

                    wAreaPartIDMap = new HashMap<>();
                    for (Integer wPartID : wPartIDList) {
                        int wID = GetAreaIDByPartID(wPartID);
                        if (wID > 0) {
                            if (wAreaPartIDMap.containsKey(wID)) {
                                List<Integer> wIDList = wAreaPartIDMap.get(wID);
                                if (wIDList.stream().noneMatch(p -> Objects.equals(p, wPartID))) {
                                    wIDList.add(wPartID);
                                }
                            } else {
                                List<Integer> wIDList = new ArrayList<>();
                                wIDList.add(wPartID);
                                wAreaPartIDMap.put(wID, wIDList);
                            }
                        }
                    }

                    // 遍历工区映射，审批日计划
                    for (Integer wAreaItemID : wAreaPartIDMap.keySet()) {
                        // 查找日计划配置
                        List<APSDayPlanAudit> wDayPlanAuditList = APSDayPlanAuditDAO.getInstance().SelectList(
                                wLoginUser,
                                -1, wAreaItemID, -1,
                                new ArrayList<>(Collections.singletonList(BPMStatus.ToAudit.getValue())),
                                wErrorCode);
                        if (wDayPlanAuditList == null) {
                            continue;
                        }
                        APSDayPlanAudit wAPSDayPlanAudit = wDayPlanAuditList.get(wDayPlanAuditList.size() - 1);
                        APSDayPlanAuditDAO.getInstance().Audit(wLoginUser, wAPSDayPlanAudit, wOperateType, wErrorCode);
                        if (wErrorCode.Result == 0 && wAPSDayPlanAudit.Status == BPMStatus.Save.getValue()) {
                            Map<Integer, List<Integer>> wTempMap = wAreaPartIDMap;
                            // 查找工序任务
                            List<APSTaskStep> wStepTaskList = wTaskList.stream()
                                    .filter(p -> wTempMap.get(wAreaItemID).stream().anyMatch(q -> q == p.PartID))
                                    .collect(Collectors.toList());
                            // 修改工序任务状态
                            wStepTaskList.forEach(p -> p.Status = APSTaskStatus.Saved.getValue());
                            for (APSTaskStep wAPSTaskStep : wStepTaskList) {
                                APSTaskStepDAO.getInstance().Update(wLoginUser, wAPSTaskStep, wErrorCode);
                            }

                            // 将工位任务状态改为“下达”
                            wTaskPartIDList = wStepTaskList.stream().map(p -> p.TaskPartID)
                                    .collect(Collectors.toList());
                            List<APSTaskPart> wTaskPartList = APSTaskPartDAO.getInstance().SelectListByIDList(
                                    wLoginUser,
                                    wTaskPartIDList, wErrorCode);
                            for (APSTaskPart wAPSTaskPart : wTaskPartList) {
                                wAPSTaskPart.Status = APSTaskStatus.Issued.getValue();
                                APSTaskPartDAO.getInstance().Update(wLoginUser, wAPSTaskPart, wErrorCode);
                            }
                        }
                    }

                    break;
                case Issued:// 下达
                    // 【日计划下达】权限控制
                    if (!CoreServiceImpl.getInstance()
                            .BMS_CheckPowerByAuthorityID(wLoginUser.CompanyID, wLoginUser.ID, 82000003, 0, 0)
                            .Info(Boolean.class)) {
                        wResult.FaultCode = RetCode.SERVER_CODE_UNROLE;
                        return wResult;
                    }
                    for (APSTaskStep wAPSTaskStep : wTaskList) {
                        if (wAPSTaskStep.Status != APSTaskStatus.Audited.getValue()
                                && wAPSTaskStep.Status != APSTaskStatus.Aborted.getValue()) {
                            wResult.FaultCode = "请选择已审批或已终止的数据!";
                            return wResult;
                        }
                        wAPSTaskStep.ReadyTime = Calendar.getInstance();
                        wAPSTaskStep.Status = APSTaskStatus.Issued.getValue();
                        APSTaskStepDAO.getInstance().Update(wLoginUser, wAPSTaskStep, wErrorCode);
                    }
                    // 工区主管下达日计划要发送通知消息给日计划中所有的工位对应的班组长
                    SendMessageToMonitor(wLoginUser, wTaskList);
                    break;
                default:
                    wResult.FaultCode += "未知操作!!!";
                    return wResult;
            }
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(StringUtils.Format("{0} {1} ex：{2}", "APSServiceImpl", "APS_AuditStepOperate", e.toString()));
        }
        return wResult;
    }

    /**
     * 关闭日计划审批消息
     */
    private void CloseMessage(BMSEmployee wLoginUser, int wDayPlanAuditID) {
        try {
            List<BFCMessage> wList = CoreServiceImpl.getInstance().BFC_GetMessageList(wLoginUser, -1,
                            BPMEventModule.SCDayAudit.getValue(), wDayPlanAuditID, -1, 0, -1, null, null)
                    .List(BFCMessage.class);
            wList.addAll(CoreServiceImpl.getInstance().BFC_GetMessageList(wLoginUser, -1,
                            BPMEventModule.SCDayAudit.getValue(), wDayPlanAuditID, -1, 1, -1, null, null)
                    .List(BFCMessage.class));
            wList.addAll(CoreServiceImpl.getInstance().BFC_GetMessageList(wLoginUser, -1,
                            BPMEventModule.SCDayAudit.getValue(), wDayPlanAuditID, -1, 2, -1, null, null)
                    .List(BFCMessage.class));
            if (wList.size() <= 0) {
                return;
            }

            wList.forEach(p -> p.Active = 4);
            CoreServiceImpl.getInstance().BFC_UpdateMessageList(wLoginUser, wList);
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    /**
     * 保存备注
     */
    private void SaveRemarks(BMSEmployee wLoginUser, List<APSTaskStep> wTaskList) {
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            List<APSTaskStep> wNotList = wTaskList.stream().filter(p -> p.Status == APSTaskStatus.Saved.getValue())
                    .collect(Collectors.toList());
            if (wNotList.size() <= 0) {
                return;
            }

            for (APSTaskStep wAPSTaskStep : wNotList) {
                wAPSTaskStep.Remark.SubmitID = wLoginUser.ID;
                wAPSTaskStep.RemarkList.add(wAPSTaskStep.Remark);
                APSTaskStepDAO.getInstance().Update(wLoginUser, wAPSTaskStep, wErrorCode);
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    /**
     * 根据工位ID获取工区
     */
    private int GetAreaIDByPartID(int wPartID) {
        int wResult = 0;
        try {
            Optional<LFSWorkAreaStation> wOption = APSConstans.GetLFSWorkAreaStationList().values().stream()
                    .filter(p -> p.StationID == wPartID).findFirst();
            if (!wOption.isPresent() || wOption.get().WorkAreaID <= 0) {
                return wResult;
            }
            wResult = wOption.get().WorkAreaID;
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
        return wResult;
    }

    private void SendMessageToMonitor(BMSEmployee wLoginUser, List<APSTaskStep> wTaskList) {
        try {
            List<Integer> wPartIDList = wTaskList.stream().map(p -> p.PartID)
                    .distinct().collect(Collectors.toList());

            Map<Integer, List<Integer>> wAreaPartIDMap = new HashMap<>();
            for (Integer wPartID : wPartIDList) {
                int wID = GetAreaIDByPartID(wPartID);
                if (wID > 0) {
                    if (wAreaPartIDMap.containsKey(wID)) {
                        List<Integer> wIDList = wAreaPartIDMap.get(wID);
                        if (wIDList.stream().noneMatch(p -> Objects.equals(p, wPartID))) {
                            wIDList.add(wPartID);
                        }
                    } else {
                        List<Integer> wIDList = new ArrayList<>();
                        wIDList.add(wPartID);
                        wAreaPartIDMap.put(wID, wIDList);
                    }
                }
            }

            List<BFCMessage> wMessageList = new ArrayList<>();
            BFCMessage wMessage = null;

            int wShiftID = MESServer.MES_QueryShiftID(wLoginUser.CompanyID, Calendar.getInstance(), APSShiftPeriod.Day,
                    FMCShiftLevel.Day, 0);
            for (Integer wAreaID : wAreaPartIDMap.keySet()) {
                List<Integer> wTempPartIDList = wAreaPartIDMap.get(wAreaID);
                for (Integer wPartID : wTempPartIDList) {
                    // 找到班组长
                    Optional<FMCWorkCharge> wOption = APSConstans.GetFMCWorkChargeList().stream()
                            .filter(p -> p.StationID == wPartID).findFirst();
                    if (!wOption.isPresent()) {
                        continue;
                    }
                    List<BMSEmployee> wMonitorList = APSConstans.GetBMSEmployeeList().values().stream()
                            .filter(p -> p.DepartmentID == wOption.get().ClassID
                                    && APSConstans.GetBMSPosition(p.Position).DutyID == 1)
                            .collect(Collectors.toList());
                    for (BMSEmployee wBMSEmployee : wMonitorList) {
                        wMessage = new BFCMessage();
                        wMessage.Active = 0;
                        wMessage.CompanyID = 0;
                        wMessage.CreateTime = Calendar.getInstance();
                        wMessage.EditTime = Calendar.getInstance();
                        wMessage.ID = 0L;
                        wMessage.MessageID = wAreaID;
                        wMessage.Title = StringUtils.Format("日计划 {0}", wShiftID);
                        wMessage.MessageText = StringUtils.Format("【{0}】 {1}下达了【{2}】日计划",
                                BPMEventModule.SCDayAudit.getLable(), wLoginUser.Name,
                                APSConstans.GetBMSDepartmentName(wAreaID));
                        wMessage.ModuleID = BPMEventModule.SCDayAudit.getValue();
                        wMessage.ResponsorID = wBMSEmployee.ID;
                        wMessage.ShiftID = wShiftID;
                        wMessage.StationID = 0L;
                        wMessage.Type = BFCMessageType.Notify.getValue();
                        wMessageList.add(wMessage);
                    }
                }
            }

            CoreServiceImpl.getInstance().BFC_UpdateMessageList(wLoginUser, wMessageList);
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    public ServiceResult<List<APSTaskPart>> APS_QueryTaskPartList(BMSEmployee wLoginUser, int wShiftID,
                                                                  int wShiftPeriod) {
        ServiceResult<List<APSTaskPart>> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            wResult.Result = APSTaskPartDAO.getInstance().SelectList(wLoginUser, -1, -1, -1, -1, -1, 1, wShiftPeriod,
                    null, wShiftID, null, null, wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode = String.valueOf(wResult.FaultCode) + e;
            logger.error(StringUtils.Format("{0} {1} ex：{2}", "APSServiceImpl", "APS_QueryTaskPartList", e.toString()));
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> APS_SaveTaskPartList(BMSEmployee wLoginUser, Calendar wStartTime, Calendar wEndTime,
                                                       List<APSTaskPart> wTaskPartList, List<APSMessage> wMessageList) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            if (wTaskPartList.size() <= 0) {
                return wResult;
            }

            OutResult<Integer> wErrorCode = new OutResult<>(0);

            // 去除开始时间大于排程的结束时间的任务
            Calendar wEndTimeC = (Calendar) wEndTime.clone();
            wEndTimeC.set(Calendar.HOUR_OF_DAY, 23);
            wEndTimeC.set(Calendar.MINUTE, 59);
            wEndTimeC.set(Calendar.SECOND, 59);

            // 保存到数据库(同步提交时间)
            Calendar wSubmitTime = Calendar.getInstance();
            wMessageList.forEach(p -> p.SubmitTime = wSubmitTime);
            wTaskPartList.forEach(p -> p.SubmitTime = wSubmitTime);

            if (wTaskPartList.size() <= 0) {
                return wResult;
            }

            // 生成ShiftID
            int wShiftPeriod = wTaskPartList.get(0).ShiftPeriod;
            int wShiftID = MESServer.MES_QueryShiftID(wLoginUser.CompanyID, (Calendar) wStartTime.clone(),
                    APSShiftPeriod.getEnumType(wShiftPeriod), FMCShiftLevel.Default, 0);
            wTaskPartList.forEach(p -> p.ShiftID = wShiftID);

            for (APSMessage wItem : wMessageList) {
                this.APS_UpdateMessage(wLoginUser, wItem);
            }
            for (APSTaskPart wItem : wTaskPartList) {
                if (wItem.ShiftPeriod == APSShiftPeriod.Week.getValue()) {
                    // 禁用同订单、同工位数据
                    List<APSTaskPart> wOldList = APSTaskPartDAO.getInstance().SelectList(wLoginUser, -1, wItem.OrderID,
                            -1, -1, wItem.PartID, 1, APSShiftPeriod.Week.getValue(), null, -1, null, null, wErrorCode);
                    if (wOldList != null && wOldList.size() > 0) {
                        wOldList.forEach(p -> p.Active = 2);
                        for (APSTaskPart wAPSTaskPart : wOldList) {
                            APSTaskPartDAO.getInstance().Update(wLoginUser, wAPSTaskPart, wErrorCode);
                        }
                        // 禁用工序任务、检验任务
                        ExecutorService wES = Executors.newFixedThreadPool(1);
                        wES.submit(() -> DisableTaskStepAndTaskIPT(wLoginUser, wOldList));
                        wES.shutdown();
                    }
                } else {
                    // 禁用同订单、同工位数据
                    List<APSTaskPart> wOldList = APSTaskPartDAO.getInstance().SelectList(wLoginUser, -1, wItem.OrderID,
                            -1, -1, wItem.PartID, 1, APSShiftPeriod.Month.getValue(), null, -1, null, null, wErrorCode);
                    if (wOldList != null && wOldList.size() > 0) {
                        wOldList.forEach(p -> p.Active = 2);
                        for (APSTaskPart wAPSTaskPart : wOldList) {
                            APSTaskPartDAO.getInstance().Update(wLoginUser, wAPSTaskPart, wErrorCode);
                        }
                    }
                }
                wItem.Active = 1;
                wItem.Status = APSTaskStatus.Saved.getValue();
                wItem.APSPlanMakeType = APSPlanMakeType.Hand.getValue();
                ServiceResult<Long> wIDResult = this.APS_UpdateTaskPart(wLoginUser, wItem);
                if (wIDResult.Result > 0) {
                    wItem.ID = wIDResult.Result.intValue();
                    if (wItem.StepPlanList != null && wItem.StepPlanList.size() > 0) {
                        /*
                         * 保存工序排程计划
                         */
                        ExecutorService wES = Executors.newFixedThreadPool(1);
                        wES.submit(() -> SaveStepPlanList(wLoginUser, wItem));
                        wES.shutdown();
                    }
                }
            }

            if (wTaskPartList.size() <= 0) {
                return wResult;
            }
            // 保存排程版本
            List<APSSchedulingVersion> wHistory = APSSchedulingVersionDAO.getInstance().SelectList(wLoginUser, -1,
                    wTaskPartList.get(0).ShiftPeriod, null, null, wErrorCode);
            int wSerialNumber = 1;
            if (wHistory.size() > 0) {
                String wNo = wHistory.stream().max(Comparator.comparing(APSSchedulingVersion::getCreateTime))
                        .get().VersionNo;
                wSerialNumber = Integer.parseInt(wNo.split("-")[2]) + 1;
            }

            DecimalFormat wDecimalFormat = new DecimalFormat("0000");
            String wFormat = wDecimalFormat.format(wSerialNumber);

            SimpleDateFormat wSDF = new SimpleDateFormat("yyyyMMdd");
            String wCurTime = wSDF.format(Calendar.getInstance().getTime());

            // 删除之前的版本
            List<APSSchedulingVersion> wHis = APSSchedulingVersionDAO.getInstance().SelectList(wLoginUser, -1,
                    wShiftPeriod, null, new ArrayList<>(Collections.singletonList(APSTaskStatus.Saved.getValue())),
                    wErrorCode);
            APSSchedulingVersionDAO.getInstance().DeleteList(wLoginUser, wHis, wErrorCode);

            APSSchedulingVersion wAPSSchedulingVersion = new APSSchedulingVersion();
            wAPSSchedulingVersion.APSShiftPeriod = wTaskPartList.get(0).ShiftPeriod;
            wAPSSchedulingVersion.CreateID = wLoginUser.ID;
            wAPSSchedulingVersion.CreateTime = Calendar.getInstance();
            wAPSSchedulingVersion.EndTime = wEndTime;
            wAPSSchedulingVersion.ID = 0;
            wAPSSchedulingVersion.StartTime = wStartTime;
            wAPSSchedulingVersion.Status = APSTaskStatus.Saved.getValue();
            wAPSSchedulingVersion.TaskPartIDList = wTaskPartList.stream().map(p -> p.ID).collect(Collectors.toList());
            wAPSSchedulingVersion.VersionNo = StringUtils.Format("{0}-{1}-{2}",
                    wTaskPartList.get(0).ShiftPeriod == APSShiftPeriod.Month.getValue() ? "M" : "W", wCurTime, wFormat);
            APSSchedulingVersionDAO.getInstance().Update(wLoginUser, wAPSSchedulingVersion, wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(StringUtils.Format("{0} {1} ex：{2}", "APSServiceImpl", "APS_SaveTaskPartList", e.toString()));
        }
        return wResult;
    }

    /**
     * 禁用工序任务和检验任务
     */
    private void DisableTaskStepAndTaskIPT(BMSEmployee wLoginUser, List<APSTaskPart> wOldList) {
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            for (APSTaskPart wAPSTaskPart : wOldList) {
                if (wAPSTaskPart.ID <= 0) {
                    continue;
                }

                List<APSTaskStep> wAPSTaskStepList = APSTaskStepDAO.getInstance().SelectList(wLoginUser, -1, -1, -1,
                        wAPSTaskPart.ID, -1, -1, -1, -1, -1, -1, null, null, null, null, wErrorCode);
                if (wAPSTaskStepList.size() <= 0) {
                    continue;
                }
                // 禁用工序任务
                for (APSTaskStep wAPSTaskStep : wAPSTaskStepList) {
                    wAPSTaskStep.Active = 2;
                    APSTaskStepDAO.getInstance().Update(wLoginUser, wAPSTaskStep, wErrorCode);
                }
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    /**
     * 保存工序排程计划
     */
    private void SaveStepPlanList(BMSEmployee wLoginUser, APSTaskPart wItem) {
        try {
            if (wItem.ID <= 0) {
                return;
            }

            /*
             * 根据TaskPartID删除工序排程计划
             */
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            APSTaskStepPlanDAO.getInstance().DeleteByTaskPartID(wLoginUser, wItem.ID, wErrorCode);

            /*
             * 遍历保存工序计划
             */
            SimpleDateFormat wSDF = new SimpleDateFormat("yyyyMMdd");
            int wShiftID = Integer.parseInt(wSDF.format(Calendar.getInstance().getTime()));
            for (APSTaskPart wAPSTaskPart : wItem.StepPlanList) {
                APSTaskStepPlan wPlan = new APSTaskStepPlan(0, wItem.OrderID, wItem.PartNo, wItem.ID, wItem.LineID,
                        wItem.PartID, wAPSTaskPart.PartID, Calendar.getInstance(), Calendar.getInstance(), wShiftID,
                        wAPSTaskPart.StartTime, wAPSTaskPart.EndTime, 1, 1, "", wItem.ProductNo, "", "", "",
                        wLoginUser.ID, "", wAPSTaskPart.TaskText, "");
                APSTaskStepPlanDAO.getInstance().Update(wLoginUser, wPlan, wErrorCode);
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    @Override
    public ServiceResult<List<APSTaskStep>> APS_QueryLeaderTask(BMSEmployee wLoginUser, Calendar wShiftDate) {
        ServiceResult<List<APSTaskStep>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            // 工区工位
            List<LFSWorkAreaStation> wAreaStationList = LFSServiceImpl.getInstance()
                    .LFS_QueryWorkAreaStationList(wLoginUser).List(LFSWorkAreaStation.class);
            // 工区人员
            List<LFSWorkAreaChecker> wAreaPersonList = LFSServiceImpl.getInstance()
                    .LFS_QueryWorkAreaCheckerList(wLoginUser).List(LFSWorkAreaChecker.class);
            if (wAreaStationList == null || wAreaStationList.size() <= 0 || wAreaPersonList == null
                    || wAreaPersonList.size() <= 0) {
                return wResult;
            }

            int wShiftID = MESServer.MES_QueryShiftID(wLoginUser.CompanyID, wShiftDate, APSShiftPeriod.Day,
                    FMCShiftLevel.Day, 0);

            if (wAreaPersonList.stream().noneMatch(p -> p.LeaderIDList != null && p.LeaderIDList.size() > 0
                    && p.LeaderIDList.stream().anyMatch(q -> q == wLoginUser.ID))) {
                return wResult;
            }

            LFSWorkAreaChecker wAreaPerson = wAreaPersonList.stream().filter(p -> p.LeaderIDList != null
                            && p.LeaderIDList.size() > 0 && p.LeaderIDList.stream().anyMatch(q -> q == wLoginUser.ID))
                    .findFirst().get();
            wAreaStationList = wAreaStationList.stream().filter(p -> p.WorkAreaID == wAreaPerson.WorkAreaID)
                    .collect(Collectors.toList());

            List<APSTaskStep> wTaskList = APSTaskStepDAO.getInstance().SelectList(wLoginUser, -1, -1, -1, -1, -1, -1,
                    -1, -1, wShiftID, 1,
                    new ArrayList<>(Arrays.asList(APSTaskStatus.Audited.getValue(),
                            APSTaskStatus.Issued.getValue(), APSTaskStatus.Aborted.getValue())),
                    null, null, null, wErrorCode);
            if (wTaskList == null || wTaskList.size() <= 0) {
                return wResult;
            }

            for (APSTaskStep wAPSTaskStep : wTaskList) {
                if (wAreaStationList.size() > 0
                        && wAreaStationList.stream().anyMatch(p -> p.StationID == wAPSTaskStep.PartID)) {
                    wResult.Result.add(wAPSTaskStep);
                }
            }

            // 去重
            if (wResult.Result != null && wResult.Result.size() > 0) {
                wResult.Result = new ArrayList<>(wResult.Result.stream()
                        .collect(Collectors.toMap(APSTaskStep::getID, account -> account, (k1, k2) -> k2)).values());
            }
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<APSTaskPart>> APS_QueryRFTaskPartList(BMSEmployee wLoginUser, int wOrderID) {
        ServiceResult<List<APSTaskPart>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            // 查询是否转向架互换了
            // Integer wChangeOrderID =
            // QMSServiceImpl.getInstance().SFC_QueryChangeOrderID(wLoginUser, wOrderID)
            // .Info(Integer.class);
            // if (wChangeOrderID > 0) {
            // // ①获取工区工位基础数据
            // List<LFSWorkAreaStation> wWSList =
            // LFSServiceImpl.getInstance().LFS_QueryWorkAreaStationList(wLoginUser)
            // .List(LFSWorkAreaStation.class);
            // wWSList = wWSList.stream().filter(p -> p.Active ==
            // 1).collect(Collectors.toList());
            // // ②获取车体和整车的工位列表
            // List<Integer> wBodyPartIDList = wWSList.stream()
            // .filter(p -> p.StationType == LFSStationType.WholeTrain.getValue()
            // || p.StationType == LFSStationType.Body.getValue())
            // .map(p -> p.StationID).collect(Collectors.toList());
            // // ③获取转向架的工位列表
            // List<Integer> wBogiesPartIDList = wWSList.stream()
            // .filter(p -> p.StationType == LFSStationType.Bogies.getValue()).map(p ->
            // p.StationID)
            // .collect(Collectors.toList());
            // // ④查询车体和整车的工位任务
            // wResult.Result.addAll(APSTaskPartDAO.getInstance().SelectList(wLoginUser, -1,
            // wOrderID, -1, -1, -1, 1,
            // APSShiftPeriod.Week.getValue(), null, -1, null, null, wBodyPartIDList,
            // wErrorCode));
            // // ⑤查询互换转向架的工位任务
            // wResult.Result.addAll(APSTaskPartDAO.getInstance().SelectList(wLoginUser, -1,
            // wChangeOrderID, -1, -1,
            // -1, 1, APSShiftPeriod.Week.getValue(), null, -1, null, null,
            // wBogiesPartIDList, wErrorCode));
            // } else {
            // wResult.Result = APSTaskPartDAO.getInstance().SelectList(wLoginUser, -1,
            // wOrderID, -1, -1, -1, 1,
            // APSShiftPeriod.Week.getValue(), null, -1, null, null, wErrorCode);
            // }

            wResult.Result = APSTaskPartDAO.getInstance().SelectList(wLoginUser, -1, wOrderID, -1, -1, -1, 1,
                    APSShiftPeriod.Week.getValue(), null, -1, null, null, wErrorCode);

            if (wResult.Result == null || wResult.Result.size() <= 0) {
                return wResult;
            }

            OMSOrder wOMSOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wResult.Result.get(0).OrderID,
                    wErrorCode);
            if (wOMSOrder == null || wOMSOrder.ID <= 0) {
                return wResult;
            }

            // 班组工位
            List<FMCWorkCharge> wWorkChargeList = APSConstans.GetFMCWorkChargeList();
            if (wWorkChargeList == null) {
                wWorkChargeList = new ArrayList<>();
            }

            // 查询转序提示
            Map<Integer, String> wTipMap = APSTaskPartDAO.getInstance().QueryTipMap(wLoginUser,
                    wResult.Result.stream().map(p -> p.ID).distinct().collect(Collectors.toList()));

            Optional<FMCWorkCharge> wOption = Optional.empty();
            for (APSTaskPart wAPSTaskPart : wResult.Result) {
                wAPSTaskPart.ControlTip = wTipMap.getOrDefault(wAPSTaskPart.ID, "");
                wAPSTaskPart.CustomerID = wOMSOrder.BureauSectionID;
                wAPSTaskPart.CustomerName = wOMSOrder.BureauSection;
                wAPSTaskPart.WBSNO = wOMSOrder.WBSNo;
                wAPSTaskPart.OrderNo = wOMSOrder.OrderNo;
                wOption = wWorkChargeList.stream().filter(p -> p.Active == 1 && p.StationID == wAPSTaskPart.PartID)
                        .findFirst();
                if (wOption.isPresent()) {
                    wAPSTaskPart.ClassID = wOption.get().ClassID;
                    wAPSTaskPart.ClassName = APSConstans.GetBMSDepartmentName(wAPSTaskPart.ClassID);
                }

                wAPSTaskPart.EndTime.add(Calendar.DATE, -1);
                Calendar wEDate = (Calendar) wAPSTaskPart.FinishWorkTime.clone();
                Calendar wSDate = (Calendar) wAPSTaskPart.EndTime.clone();
                wAPSTaskPart.DelayHours = getDateDays(wEDate, wSDate);
            }

            // 查询工序进度
            List<Integer> TaskPartIDList = wResult.Result.stream().map(p -> p.ID).collect(Collectors.toList());

            List<APSTaskPart> wWSList = APSTaskPartDAO.getInstance().SelectListProgress(wLoginUser, TaskPartIDList,
                    wErrorCode);
            for (APSTaskPart wItem : wResult.Result) {
                if (wWSList.stream().anyMatch(p -> p.ID == wItem.ID)) {
                    APSTaskPart wTaskPat = wWSList.stream().filter(p -> p.ID == wItem.ID).findFirst().get();

                    wItem.PointSize = wTaskPat.PointSize;
                    wItem.PointFinishSize = wTaskPat.PointFinishSize;
                }
            }

            // 排序
            SortPartList(wLoginUser, wResult.Result, wOMSOrder.ID);
            // 剔除保存状态的工位
            wResult.Result.removeIf(p -> p.Status == 1);

            // 查询终检工位任务
            List<APSTaskPart> wFinalCheckTask = APSTaskPartDAO.getInstance().GetFinalCheckTask(wLoginUser, wOrderID,
                    wWorkChargeList,
                    wErrorCode);
            wResult.CustomResult.put("FinalCheckTask", wFinalCheckTask);
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @SuppressWarnings("unused")
    private void UpdateTaskStepStatus() {
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            List<Integer> wTaskStepIDList = APSTaskStepDAO.getInstance()
                    .SelectNotRealFinishedTaskStepIDList(BaseDAO.SysAdmin, wErrorCode);
            for (Integer wTaskStepID : wTaskStepIDList) {
                APSTaskStep wTaskStep = APSTaskStepDAO.getInstance().SelectByID(BaseDAO.SysAdmin, wTaskStepID,
                        wErrorCode);
                if (wTaskStep != null && wTaskStep.ID > 0) {
                    wTaskStep.Status = 4;
                    APSTaskStepDAO.getInstance().Update(BaseDAO.SysAdmin, wTaskStep, wErrorCode);
                }
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    /**
     * 排序
     */
    private void SortPartList(BMSEmployee wLoginUser, List<APSTaskPart> wList, int wOrderID) {
        try {
            // ①获取工位顺序字典
            Map<Integer, Integer> wPartMap = APSTaskPartDAO.getInstance().SelectPartOrderMap(wLoginUser, wOrderID);
            // ②顺序赋值
            for (APSTaskPart wAPSTaskPart : wList) {
                wAPSTaskPart.PartOrder = wPartMap.getOrDefault(wAPSTaskPart.PartID, 100);
            }
            // ③排序
            wList.sort(Comparator.comparing(APSTaskPart::getPartOrder));
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    public ServiceResult<APSWorkHour> APS_QueryWorkHour(BMSEmployee wLoginUser) {
        ServiceResult<APSWorkHour> wResult = new ServiceResult<>();
        wResult.Result = new APSWorkHour();
        try {
            // wResult.Result = XmlTool.ReadXml(Constants.getConfigPath() +
            // "APSWorkHour.xml");
            OutResult<Integer> wErrorCode = new OutResult<Integer>(0);
            wResult.Result.MinWorkHour = StringUtils
                    .parseInt(MESSystemConfigDAO.getInstance().SelectValueByKey(wLoginUser, "MinWorkHour",
                            wErrorCode));
            wResult.Result.MiddleWorkHour = StringUtils
                    .parseInt(MESSystemConfigDAO.getInstance().SelectValueByKey(wLoginUser,
                            "MiddleWorkHour", wErrorCode));
            wResult.Result.MaxWorkHour = StringUtils
                    .parseInt(MESSystemConfigDAO.getInstance().SelectValueByKey(wLoginUser, "MaxWorkHour",
                            wErrorCode));
        } catch (Exception e) {
            wResult.FaultCode = wResult.FaultCode + e;
            logger.error(e.toString());
        }
        return wResult;
    }

    public ServiceResult<Integer> APS_SaveWorkHour(BMSEmployee wLoginUser, int wMinWorkHour, int wMiddleWorkHour,
                                                   int wMaxWorkHour) {
        ServiceResult<Integer> wResult = new ServiceResult<>();
        try {
            APSWorkHour wAPSWorkHour = new APSWorkHour();
            wAPSWorkHour.MaxWorkHour = wMaxWorkHour;
            wAPSWorkHour.MiddleWorkHour = wMiddleWorkHour;
            wAPSWorkHour.MinWorkHour = wMinWorkHour;

            XmlTool.SaveXml(Constants.getConfigPath() + "APSWorkHour.xml", wAPSWorkHour);
        } catch (Exception e) {
            wResult.FaultCode = wResult.FaultCode + e;
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Boolean> APS_CheckIsExist(BMSEmployee wLoginUser, Calendar wStartTime,
                                                   APSShiftPeriod wShiftPeriod) {
        ServiceResult<Boolean> wResult = new ServiceResult<>();
        wResult.Result = false;
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            List<APSSchedulingVersionBPM> wList = APSSchedulingVersionBPMDAO.getInstance().SelectList(wLoginUser, -1,
                    "", -1, -1, "", "", wShiftPeriod.getValue(), -1, new ArrayList<>(Arrays.asList(2, 3, 4, 5)), null,
                    null, null, wErrorCode);
            if (wList != null && wList.size() > 0) {
                wResult.Result = true;
            }
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> APS_QueryTodayToDoTaskPartList(BMSEmployee wLoginUser) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            wResult.Result = APSTaskPartDAO.getInstance().SelectTodayToDoList(wLoginUser, wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    public ServiceResult<List<APSSchedulingVersion>> APS_QueryHistoryVersionList(BMSEmployee wLoginUser,
                                                                                 int wAPSShiftPeriod,
                                                                                 Calendar wStartTime,
                                                                                 Calendar wEndTime) {
        ServiceResult<List<APSSchedulingVersion>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            wResult.Result = APSSchedulingVersionDAO.getInstance().SelectListByTime(wLoginUser, wAPSShiftPeriod,
                    wStartTime, wEndTime, wErrorCode);
            for (APSSchedulingVersion wAPSSchedulingVersion : wResult.Result) {
                wAPSSchedulingVersion.APSTaskPartList = APSTaskPartDAO.getInstance().SelectListByIDList(wLoginUser,
                        wAPSSchedulingVersion.TaskPartIDList, wErrorCode);
                // 工位排序
                OrderPart(wAPSSchedulingVersion.APSTaskPartList);
                wAPSSchedulingVersion.OMSOrderList = OMSOrderDAO.getInstance().SelectListByIDList(wLoginUser,
                        wAPSSchedulingVersion.APSTaskPartList.stream().map(p -> p.OrderID).distinct()
                                .collect(Collectors.toList()),
                        wErrorCode);
            }
        } catch (Exception e) {
            wResult.FaultCode = String.valueOf(wResult.FaultCode) + e;
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<FMCWorkspace>> APS_QueryPartNoStatus(BMSEmployee wLoginUser, List<FMCWorkspace> wList) {
        ServiceResult<List<FMCWorkspace>> wResult = new ServiceResult<>();
        wResult.Result = wList;
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            OMSOrder wOrder = null;
            List<OMSOrder> wOrderList = null;
            List<RSMTurnOrderTask> wTurnOrdeList = null;
            List<APSTaskPart> wTaskPartList = null;
            for (FMCWorkspace wFMCWorkspace : wList) {
                wFMCWorkspace.PartNo = wFMCWorkspace.PartNo.replace("[A]", "").replace("[B]", "");
                wOrderList = OMSOrderDAO.getInstance().SelectList(wLoginUser, -1, -1, "", -1, -1, -1,
                        wFMCWorkspace.PartNo, "", 1, null, null, null, null, null, wErrorCode);
                if (wOrderList == null || wOrderList.size() <= 0) {
                    continue;
                }
                wOrder = wOrderList.get(0);
                wTurnOrdeList = QMSServiceImpl.getInstance()
                        .RSM_QueryTurnOrderTaskList(wLoginUser, wOrder.ID, -1, -1, null).List(RSMTurnOrderTask.class);
                if (wTurnOrdeList == null || wTurnOrdeList.size() <= 0) {
                    wTaskPartList = APSTaskPartDAO.getInstance().SelectList(wLoginUser, -1, wOrder.ID, -1, -1,
                            APSConstans.YJStationID, 1, APSShiftPeriod.Week.getValue(), null, -1, null, null,
                            wErrorCode);
                    if (wTaskPartList != null && wTaskPartList.size() > 0
                            && wTaskPartList.stream().anyMatch(p -> p.Status == APSTaskStatus.Issued.getValue())) {
                        wFMCWorkspace.Status = 3;
                    } else if (wTaskPartList != null && wTaskPartList.size() > 0
                            && wTaskPartList.stream().anyMatch(p -> p.Status == APSTaskStatus.Started.getValue())) {
                        wFMCWorkspace.Status = 4;
                    } else if (wTaskPartList != null && wTaskPartList.size() > 0
                            && wTaskPartList.stream().anyMatch(p -> p.Status == APSTaskStatus.Done.getValue())) {
                        wFMCWorkspace.Status = 5;
                    }
                } else {
                    Calendar wApplyTime = wTurnOrdeList.stream()
                            .max(Comparator.comparing(RSMTurnOrderTask::getApplyTime)).get().ApplyTime;
                    wTurnOrdeList = wTurnOrdeList.stream().filter(p -> p.ApplyTime.compareTo(wApplyTime) == 0)
                            .collect(Collectors.toList());
                    for (RSMTurnOrderTask wRSMTurnOrderTask : wTurnOrdeList) {
                        if (wRSMTurnOrderTask.Status == SFCTurnOrderTaskStatus.Auditing.getValue()) {
                            wTaskPartList = APSTaskPartDAO.getInstance().SelectList(wLoginUser, -1, wOrder.ID, -1, -1,
                                    wRSMTurnOrderTask.ApplyStationID, 1, APSShiftPeriod.Week.getValue(), null, -1, null,
                                    null, wErrorCode);
                            if (wTaskPartList != null && wTaskPartList.size() > 0 && wTaskPartList.stream()
                                    .anyMatch(p -> p.Status == APSTaskStatus.Issued.getValue())) {
                                wFMCWorkspace.Status = 3;
                            } else if (wTaskPartList != null && wTaskPartList.size() > 0 && wTaskPartList.stream()
                                    .anyMatch(p -> p.Status == APSTaskStatus.Started.getValue())) {
                                wFMCWorkspace.Status = 4;
                            } else if (wTaskPartList != null && wTaskPartList.size() > 0 && wTaskPartList.stream()
                                    .anyMatch(p -> p.Status == APSTaskStatus.Done.getValue())) {
                                wFMCWorkspace.Status = 5;
                            }
                        } else if (wRSMTurnOrderTask.Status == SFCTurnOrderTaskStatus.Passed.getValue()) {
                            wTaskPartList = APSTaskPartDAO.getInstance().SelectList(wLoginUser, -1, wOrder.ID, -1, -1,
                                    wRSMTurnOrderTask.TargetStationID, 1, APSShiftPeriod.Week.getValue(), null, -1,
                                    null, null, wErrorCode);
                            if (wTaskPartList != null && wTaskPartList.size() > 0 && wTaskPartList.stream()
                                    .anyMatch(p -> p.Status == APSTaskStatus.Issued.getValue())) {
                                wFMCWorkspace.Status = 3;
                            } else if (wTaskPartList != null && wTaskPartList.size() > 0 && wTaskPartList.stream()
                                    .anyMatch(p -> p.Status == APSTaskStatus.Started.getValue())) {
                                wFMCWorkspace.Status = 4;
                            } else if (wTaskPartList != null && wTaskPartList.size() > 0 && wTaskPartList.stream()
                                    .anyMatch(p -> p.Status == APSTaskStatus.Done.getValue())) {
                                wFMCWorkspace.Status = 5;
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    /**
     * 自动补齐工序同时返回订单列表和工位列表
     */
    private ServiceResult<List<OMSOrder>> GetOrderListAndTaskPartListWithWholeTaskStep(BMSEmployee wLoginUser,
                                                                                       List<APSTaskStep> wStepTaskList, List<FPCRoutePart> wFPCRoutePartList,
                                                                                       List<FPCRoutePartPoint> wFPCRoutePartPointList) {
        ServiceResult<List<OMSOrder>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            if (wStepTaskList == null || wStepTaskList.size() <= 0) {
                wResult.CustomResult.put("TaskPartList", new ArrayList<APSTaskPartDetails>());
                wResult.CustomResult.put("TaskStepList", new ArrayList<>());
                return wResult;
            }

            // 根据订单ID集合获取订单列表
            List<Integer> wOrderIDList = wStepTaskList.stream().map(p -> p.OrderID).distinct()
                    .collect(Collectors.toList());
            wResult.Result = OMSOrderDAO.getInstance().SelectListByIDList(wLoginUser, wOrderIDList, wErrorCode);

            // 根据工位任务ID集合获取所有工位任务
            List<Integer> wTaskPartIDList = wStepTaskList.stream().map(p -> p.TaskPartID).distinct()
                    .collect(Collectors.toList());
            List<APSTaskPart> wTaskPartList = APSTaskPartDAO.getInstance().SelectListByIDList(wLoginUser,
                    wTaskPartIDList, wErrorCode);
            wTaskPartList = wTaskPartList.stream().filter(p -> p.Active == 1).collect(Collectors.toList());

            List<APSTaskStep> wAllStepList = new ArrayList<>();

            List<Integer> wPartPointIDList = null;
            List<APSTaskPartDetails> wDetailsList = new ArrayList<>();
            APSTaskPartDetails wAPSTaskPartDetails = null;
            List<APSTaskStep> wTaskStepList = null;

            List<LFSWorkAreaStation> wAreaStationList = LFSServiceImpl.getInstance()
                    .LFS_QueryWorkAreaStationList(wLoginUser).List(LFSWorkAreaStation.class);

            int wRouteID = 0;

            List<APSTaskStep> wAllTaskStepList = new ArrayList<>();
            if (wTaskPartList.size() > 0) {
                wAllTaskStepList = APSTaskStepDAO.getInstance().SelectListByTaskPartIDList(wLoginUser,
                        wTaskPartList.stream().map(p -> p.ID).collect(Collectors.toList()), wErrorCode);
            }

            // 基本时间
            Calendar wBaseTime = Calendar.getInstance();
            wBaseTime.set(2000, 0, 1);

            for (APSTaskPart wAPSTaskPart : wTaskPartList) {
                OMSOrder wOrder = wResult.Result.stream().filter(p -> p.ID == wAPSTaskPart.OrderID).findFirst().get();
                if (wOrder.ID > 0) {
                    wRouteID = wOrder.RouteID;
                    if (wAPSTaskPart.RouteID > 0) {
                        wRouteID = wAPSTaskPart.RouteID;
                    }
                }
                // 工艺工序列表
                wPartPointIDList = APS_GetPartPointIDList(wFPCRoutePartList, wFPCRoutePartPointList,
                        wAPSTaskPart.PartID, wRouteID);
                // 工序任务列表
                wTaskStepList = wAllTaskStepList.stream().filter(p -> p.TaskPartID == wAPSTaskPart.ID)
                        .collect(Collectors.toList());

                List<APSTaskStep> wTempList = wTaskStepList;
                List<Integer> wNotSaveList = wPartPointIDList.stream()
                        .filter(p -> wTempList.stream().noneMatch(q -> q.StepID == p)).collect(Collectors.toList());

                if (wNotSaveList.size() > 0) {
                    for (int wNewStepID : wNotSaveList) {
                        APSTaskStep wAPSTaskStep = new APSTaskStep();

                        wAPSTaskStep.Active = 1;
                        wAPSTaskStep.ID = 0;
                        wAPSTaskStep.LineID = wAPSTaskPart.LineID;
                        wAPSTaskStep.MaterialNo = wAPSTaskPart.MaterialNo;
                        wAPSTaskStep.OrderID = wAPSTaskPart.OrderID;
                        wAPSTaskStep.PartID = wAPSTaskPart.PartID;
                        wAPSTaskStep.PartNo = wAPSTaskPart.PartNo;
                        wAPSTaskStep.PlanerID = wLoginUser.ID;
                        wAPSTaskStep.ProductNo = wAPSTaskPart.ProductNo;
                        wAPSTaskStep.ShiftID = 0;
                        wAPSTaskStep.Status = APSTaskStatus.Saved.getValue();
                        wAPSTaskStep.StepID = wNewStepID;
                        wAPSTaskStep.TaskPartID = wAPSTaskPart.ID;
                        wAPSTaskStep.TaskLineID = wAPSTaskPart.TaskLineID;
                        wAPSTaskStep.TaskText = wAPSTaskPart.TaskText;
                        wAPSTaskStep.WorkHour = 0;
                        wAPSTaskStep.WorkShopID = wAPSTaskPart.WorkShopID;
                        wAPSTaskStep.StartTime = wBaseTime;
                        wAPSTaskStep.EndTime = wBaseTime;
                        wAPSTaskStep.ReadyTime = wBaseTime;
                        wAPSTaskStep.CreateTime = Calendar.getInstance();

                        wAPSTaskStep.ID = APSTaskStepDAO.getInstance().Update(wLoginUser, wAPSTaskStep, wErrorCode);
                        wTaskStepList.add(wAPSTaskStep);
                    }
                }

                // 工位详情
                wAPSTaskPartDetails = new APSTaskPartDetails();
                wAPSTaskPartDetails.APSTaskPart = wAPSTaskPart;
                wAPSTaskPartDetails.OrderNum = wAPSTaskPart.ID;
                wAPSTaskPartDetails.PartID = wAPSTaskPart.PartID;
                wAPSTaskPartDetails.ShiftDate = wAPSTaskPart.StartTime;
                wAPSTaskPartDetails.PartNo = wOrder.PartNo;
                wAPSTaskPartDetails.OrderID = wOrder.ID;
                // 工序总数
                wAPSTaskPartDetails.StepSize = wPartPointIDList.size();
                // 工序完成数
                wAPSTaskPartDetails.StepFinish = (int) wTaskStepList.stream()
                        .filter(p -> p.Status == APSTaskStatus.Done.getValue()).count();
                // 工序在制数
                wAPSTaskPartDetails.StepMaking = (int) wTaskStepList.stream()
                        .filter(p -> p.Status == APSTaskStatus.Submit.getValue()
                                || p.Status == APSTaskStatus.ToAudit.getValue()
                                || p.Status == APSTaskStatus.Audited.getValue())
                        .count();
                // 工序已排数
                wAPSTaskPartDetails.StepSchedule = (int) wTaskStepList.stream()
                        .filter(p -> p.Status == APSTaskStatus.Issued.getValue()
                                || p.Status == APSTaskStatus.Started.getValue()
                                || p.Status == APSTaskStatus.Done.getValue())
                        .count();

                if (wAreaStationList != null && wAreaStationList.size() > 0 && wAreaStationList.stream()
                        .anyMatch(p -> p.StationID == wAPSTaskPart.PartID && p.WorkAreaID > 0)) {
                    wAPSTaskPartDetails.AreaID = wAreaStationList.stream()
                            .filter(p -> p.StationID == wAPSTaskPart.PartID && p.WorkAreaID > 0).findFirst()
                            .get().WorkAreaID;
                    wAPSTaskPartDetails.AreaName = APSConstans.GetBMSDepartmentName(wAPSTaskPartDetails.AreaID);
                }

                wDetailsList.add(wAPSTaskPartDetails);
                wAllStepList.addAll(wTaskStepList);
            }

            // 排序
            if (wDetailsList.size() > 0) {
                wDetailsList.sort(Comparator.comparing(APSTaskPartDetails::getPartNo)
                        .thenComparing(APSTaskPartDetails::getAreaID).thenComparing(APSTaskPartDetails::getOrderNum)
                        .thenComparing(APSTaskPartDetails::getShiftDate));
            }

            wResult.CustomResult.put("TaskPartList", wDetailsList);
            wResult.CustomResult.put("TaskStepList", wAllStepList);
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    private ServiceResult<List<OMSOrder>> GetOrderListAndTaskPartListByTaskStepList(BMSEmployee wLoginUser,
                                                                                    List<APSTaskStep> wStepTaskList,
                                                                                    List<FPCRoutePart> wFPCRoutePartList,
                                                                                    List<FPCRoutePartPoint> wFPCRoutePartPointList) {
        ServiceResult<List<OMSOrder>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        try {
            if (wStepTaskList == null || wStepTaskList.size() <= 0) {
                wResult.CustomResult.put("TaskPartList", new ArrayList<APSTaskPartDetails>());
                return wResult;
            }
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            List<Integer> wOrderIDList = wStepTaskList.stream().map(p -> p.OrderID).distinct()
                    .collect(Collectors.toList());
            List<Integer> wTaskPartIDList = wStepTaskList.stream().map(p -> p.TaskPartID).distinct()
                    .collect(Collectors.toList());

            wResult.Result = OMSOrderDAO.getInstance().SelectListByIDList(wLoginUser, wOrderIDList, wErrorCode);
            List<APSTaskPart> wTaskPartList = APSTaskPartDAO.getInstance().SelectListByIDList(wLoginUser,
                    wTaskPartIDList, wErrorCode);

            List<Integer> wPartPointIDList = null;

            List<APSTaskPartDetails> wDetailsList = new ArrayList<>();
            APSTaskPartDetails wAPSTaskPartDetails = null;
            List<APSTaskStep> wTaskStepList = null;
            List<LFSWorkAreaStation> wAreaStationList = LFSServiceImpl.getInstance()
                    .LFS_QueryWorkAreaStationList(wLoginUser).List(LFSWorkAreaStation.class);

            // 所有工序任务列表
            List<APSTaskStep> wAllTaskStepList = APSTaskStepDAO.getInstance().SelectListByTaskPartIDList(wLoginUser,
                    wStepTaskList.stream().map(p -> p.TaskPartID).distinct().collect(Collectors.toList()), wErrorCode);

            int wRouteID = 0;
            for (APSTaskPart wAPSTaskPart : wTaskPartList) {
                OMSOrder wOrder = wResult.Result.stream().filter(p -> p.ID == wAPSTaskPart.OrderID).findFirst().get();
                if (wOrder.ID > 0) {
                    wRouteID = wOrder.RouteID;
                }
                // 工艺工序列表
                wPartPointIDList = APS_GetPartPointIDList(wFPCRoutePartList, wFPCRoutePartPointList,
                        wAPSTaskPart.PartID, wRouteID);
                // 工序任务列表
                wTaskStepList = wAllTaskStepList.stream().filter(p -> p.TaskPartID == wAPSTaskPart.ID)
                        .collect(Collectors.toList());
                // 工位详情
                wAPSTaskPartDetails = new APSTaskPartDetails();
                wAPSTaskPartDetails.APSTaskPart = wAPSTaskPart;
                // 工序总数
                wAPSTaskPartDetails.StepSize = wPartPointIDList.size();
                // 工序完成数
                wAPSTaskPartDetails.StepFinish = (int) wTaskStepList.stream()
                        .filter(p -> p.Status == APSTaskStatus.Done.getValue()).count();
                // 工序在制数
                wAPSTaskPartDetails.StepMaking = (int) wTaskStepList.stream()
                        .filter(p -> p.Status == APSTaskStatus.Submit.getValue()
                                || p.Status == APSTaskStatus.ToAudit.getValue()
                                || p.Status == APSTaskStatus.Audited.getValue())
                        .count();
                // 工序已排数
                wAPSTaskPartDetails.StepSchedule = (int) wTaskStepList.stream()
                        .filter(p -> p.Status == APSTaskStatus.Issued.getValue()
                                || p.Status == APSTaskStatus.Started.getValue()
                                || p.Status == APSTaskStatus.Done.getValue())
                        .count();

                if (wAreaStationList != null && wAreaStationList.size() > 0 && wAreaStationList.stream()
                        .anyMatch(p -> p.StationID == wAPSTaskPart.PartID && p.WorkAreaID > 0)) {
                    wAPSTaskPartDetails.AreaID = wAreaStationList.stream()
                            .filter(p -> p.StationID == wAPSTaskPart.PartID && p.WorkAreaID > 0).findFirst()
                            .get().WorkAreaID;
                }

                wDetailsList.add(wAPSTaskPartDetails);
            }
            wResult.CustomResult.put("TaskPartList", wDetailsList);
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    /**
     * 获取待竣工确认的订单列表
     */
    @Override
    public ServiceResult<List<OMSOrder>> APS_QueryCompleteOrderList(BMSEmployee wLoginUser) {
        ServiceResult<List<OMSOrder>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            // ①获取所有维修中的订单列表
            List<OMSOrder> wOrderList = OMSOrderDAO.getInstance().SelectList(wLoginUser, -1, -1, "", -1, -1, -1, "", "",
                    1, new ArrayList<>(Collections.singletonList(OMSOrderStatus.Repairing.getValue())), null, null,
                    null,
                    null, wErrorCode);
            if (wOrderList == null || wOrderList.size() <= 0) {
                return wResult;
            }
            wResult.Result = wOrderList;
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> APS_CompleteConfirm(BMSEmployee wLoginUser, int wOrderID, List<String> wImagePathList,
                                                      String wRemark) {
        ServiceResult<Integer> wResult = new ServiceResult<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            OMSOrder wOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wOrderID, wErrorCode);
            if (wOrder == null || wOrder.ID <= 0) {
                wResult.FaultCode += RetCode.SERVER_RST_ERROR_OUT;
                return wResult;
            }

            if (wOrder.Status != OMSOrderStatus.Repairing.getValue()) {
                wResult.FaultCode += "提示：请选择状态为“维修中”的订单!";
                return wResult;
            }

            List<FPCRoutePart> wFPCRoutePartList = FMCServiceImpl.getInstance()
                    .FPC_QueryRoutePartListByRouteID(wLoginUser, 0).List(FPCRoutePart.class);
            List<FPCRoutePartPoint> wFPCRoutePartPointList = FMCServiceImpl.getInstance()
                    .FPC_QueryRoutePartPointListByRouteID(wLoginUser, 0, 0).List(FPCRoutePartPoint.class);

            List<Integer> wPartIDList = APSUtils.getInstance().APS_GetPartIDListByOrder(wOrder,
                    wFPCRoutePartList);
            if (wPartIDList == null || wPartIDList.size() <= 0) {
                wResult.FaultCode += "提示：该订单暂时未设置工艺路线!";
                return wResult;
            }

            int wRouteID = wOrder.RouteID;

            // 终检工位列表
            List<FPCPart> wQTFinals = FMCServiceImpl.getInstance()
                    .FPC_QueryPartList(wLoginUser, -1, -1, -1, FPCPartTypes.QTFinally.getValue()).List(FPCPart.class);

            for (int wPartID : wPartIDList) {
                // ③根据订单、工位获取工位任务
                List<APSTaskPart> wTaskPartList = APSTaskPartDAO.getInstance().SelectList(wLoginUser, -1, wOrder.ID, -1,
                        wOrder.LineID, wPartID, 1, APSShiftPeriod.Week.getValue(), null, -1, null, null, wErrorCode);
                if (wTaskPartList == null || wTaskPartList.size() <= 0) {
                    wResult.FaultCode += StringUtils.Format("提示：【{0}】工位任务未下达!", APSConstans.GetFPCPart(wPartID).Name);
                    return wResult;
                }
                // ④根据订单、工位获取所有工序ID集合
                List<Integer> wPartPointIDList = APS_GetPartPointIDList(wFPCRoutePartList, wFPCRoutePartPointList,
                        wPartID, wRouteID);
                if (wPartPointIDList == null || wPartPointIDList.size() <= 0) {
                    wResult.FaultCode += StringUtils.Format("提示：【{0}】工位下无工序!", APSConstans.GetFPCPart(wPartID).Name);
                    return wResult;
                }
                // ⑤根据工位任务获取所有工序任务列表
                List<APSTaskStep> wTaskStepList = APSTaskStepDAO.getInstance().SelectList(wLoginUser, -1, -1, -1,
                        wTaskPartList.get(0).ID, -1, -1, -1, -1, -1, 1, null, null, null, null, wErrorCode);
                if (wTaskStepList == null || wTaskStepList.size() <= 0) {
                    wResult.FaultCode += StringUtils.Format("提示：【{0}】工位下无工序任务!", APSConstans.GetFPCPart(wPartID).Name);
                    return wResult;
                }
                // ⑥判断是否所有工序都有工序任务，且所有工序任务状态都为完工，若成立，则取，若不成立，则弃。
                if (!wPartPointIDList.stream().allMatch(p -> wTaskStepList.stream()
                        .anyMatch(q -> p == q.StepID && q.Status == APSTaskStatus.Done.getValue()))) {
                    Integer wStepID = wPartPointIDList.stream()
                            .filter(p -> wTaskStepList.stream()
                                    .noneMatch(q -> p == q.StepID && q.Status == APSTaskStatus.Done.getValue()))
                            .findFirst().get();
                    wResult.FaultCode += StringUtils.Format("提示：【{0}】工位下【{1}】工序未完工!",
                            APSConstans.GetFPCPart(wPartID).Name, APSConstans.GetFPCPartPointName(wStepID));
                    return wResult;
                }
                // ⑦判断此工位是否有质量工位触发，且该工位的工序任务全部完工
                if (wQTFinals != null && wQTFinals.size() > 0
                        && wQTFinals.stream().anyMatch(p -> p.QTPartID == wPartID)) {
                    List<FPCPart> wTempPartList = wQTFinals.stream().filter(p -> p.QTPartID == wPartID)
                            .collect(Collectors.toList());
                    for (FPCPart wItem : wTempPartList) {
                        // 获取该工位下所有工序
                        List<Integer> wQTStepIDList = APSUtils.getInstance().FMC_QueryStepIDList(wLoginUser,
                                wOrder.LineID, wItem.ID, wOrder.ProductID);
                        if (wQTStepIDList == null || wQTStepIDList.size() <= 0) {
                            wResult.FaultCode += StringUtils.Format("提示：【{0}】工位下无工序!",
                                    APSConstans.GetFPCPartName(wItem.ID));
                            return wResult;
                        }
                        for (int wStepID : wQTStepIDList) {
                            List<APSTaskStep> wQTStepTaskList = APSTaskStepDAO.getInstance().SelectList(wLoginUser, -1,
                                    wOrder.ID, -1, -1, -1, wOrder.LineID, wItem.ID, wStepID, -1, 1, null, null, null,
                                    null, wErrorCode);
                            if (wQTStepTaskList == null || wQTStepIDList.size() <= 0) {
                                wResult.FaultCode += StringUtils.Format("提示：【{0}】工位下【{1}】工序未生成日计划!",
                                        APSConstans.GetFPCPartName(wItem.ID));
                                return wResult;
                            }
                            if (wQTStepTaskList.stream().anyMatch(p -> p.Status != APSTaskStatus.Done.getValue())) {
                                wResult.FaultCode += StringUtils.Format("提示：【{0}】工位下【{1}】工序未完工!",
                                        APSConstans.GetFPCPartName(wItem.ID), APSConstans.GetFPCPartPointName(wStepID));
                                return wResult;
                            }

                            // 判断所有不合格项是否发起不合格评审
                            String wCheckResult = this.IsSendRepair(wLoginUser, wOrder, wItem.ID, wStepID);
                            if (StringUtils.isNotEmpty(wCheckResult)) {
                                wResult.FaultCode += wCheckResult;
                                return wResult;
                            }
                        }
                    }
                }
            }

            // ⑧检查该订单的不合格评审单是否全部完成
            int wNCRNumber = AndonDAO.getInstance().SelectNcrCountNF(wLoginUser, wOrder.ID, null, wErrorCode);
            if (wNCRNumber > 0) {
                wResult.FaultCode += "提示：该订单有未完成的不合格评审单!";
                return wResult;
            }
            // ⑨检查该订单的返修单是否全部完成
            int wRepairNumber = AndonDAO.getInstance().SelectRepairCountNF(wLoginUser, wOrder.ID, null, wErrorCode);
            if (wRepairNumber > 0) {
                wResult.FaultCode += "提示：该订单有未完成的返修单!";
                return wResult;
            }

            // ⑩生成竣工确认单，且将订单状态改为已完工
            List<SFCOrderForm> wOrderList = SFCOrderFormDAO.getInstance().SelectList(wLoginUser, -1, wOrder.ID, "", 1,
                    null, wErrorCode);
            if (wOrderList != null && wOrderList.size() > 0) {
                SFCOrderForm wSFCOrderForm = wOrderList.get(0);
                wSFCOrderForm.ConfirmID = wLoginUser.ID;
                wSFCOrderForm.ConfirmTime = Calendar.getInstance();
                wSFCOrderForm.Status = 2;
                if (wImagePathList != null && wImagePathList.size() > 0) {
                    wSFCOrderForm.ImagePathList = wImagePathList;
                }
                if (StringUtils.isNotEmpty(wRemark)) {
                    wSFCOrderForm.Remark = wRemark;
                }
                SFCOrderFormDAO.getInstance().Update(wLoginUser, wSFCOrderForm, wErrorCode);

                wOrder.Status = OMSOrderStatus.FinishedWork.getValue();
                wOrder.RealFinishDate = Calendar.getInstance();
                OMSOrderDAO.getInstance().Update(BaseDAO.SysAdmin, wOrder, wErrorCode);
            } else {
                wResult.FaultCode += "提示：该订单的竣工确认单缺失!";
                return wResult;
            }
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    /**
     * 判断某订单的终检工位、工序任务不合格检验项是否发起返修
     */
    private String IsSendRepair(BMSEmployee wLoginUser, OMSOrder wOrder, int wPartID, int wStepID) {
        String wResult = "";
        try {
            List<SFCTaskIPT> wIPTList = QMSServiceImpl.getInstance().SFC_QueryTaskIPTList(wLoginUser, wOrder.ID)
                    .List(SFCTaskIPT.class);
            if (wIPTList == null || wIPTList.size() <= 0) {
                return wResult;
            }
            List<SFCTaskIPT> wTaskIPTList = wIPTList.stream().filter(
                            p -> p.PartID == wPartID && p.PartPointID == wStepID && p.TaskType == SFCTaskType.Final.getValue())
                    .collect(Collectors.toList());
            if (wTaskIPTList.size() <= 0) {
                return wResult;
            }

            for (SFCTaskIPT wSFCTaskIPT : wTaskIPTList) {
                List<IPTValue> wValueList = QMSServiceImpl.getInstance().IPT_QueryValueList(wLoginUser, wSFCTaskIPT.ID)
                        .List(IPTValue.class);
                if (wValueList == null || wValueList.size() <= 0) {
                    continue;
                }
                List<IPTValue> wNotQualityValues = wValueList.stream().filter(p -> p.Result == 2)
                        .collect(Collectors.toList());
                if (wNotQualityValues.size() <= 0) {
                    continue;
                }

                for (IPTValue wIPTValue : wNotQualityValues) {
                    if (!MyHelperServiceImpl.getInstance().WDW_IsSendRepair(wLoginUser, wSFCTaskIPT.ID,
                            (int) wIPTValue.IPTItemID).Result) {
                        wResult = StringUtils.Format("提示：【{0}】工序中有未发起返修的不合格项!", wSFCTaskIPT.PartPointName);
                        return wResult;
                    }
                }
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<OMSOrder>> APS_QueryOutApplyOrderList(BMSEmployee wLoginUser) {
        ServiceResult<List<OMSOrder>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            List<OMSOrder> wOrderList = OMSOrderDAO.getInstance()
                    .SelectList(wLoginUser, -1, -1, "", -1, -1, -1, "", "", 1,
                            new ArrayList<>(Arrays.asList(OMSOrderStatus.FinishedWork.getValue(),
                                    OMSOrderStatus.ToOutChcek.getValue(), OMSOrderStatus.ToOutConfirm.getValue(),
                                    OMSOrderStatus.CarSended.getValue())),
                            null, null, null, null, wErrorCode);
            if (wOrderList == null || wOrderList.size() <= 0) {
                wResult.CustomResult.put("OrderMap", new HashMap<Integer, Boolean>());
                return wResult;
            }

            Map<Integer, SFCOrderForm> wMap = new HashMap<>();
            for (OMSOrder wOMSOrder : wOrderList) {
                List<SFCOrderForm> wList = SFCOrderFormDAO.getInstance().SelectList(wLoginUser, -1, wOMSOrder.ID, "", 2,
                        null, wErrorCode);
                if (wList != null && wList.size() > 0) {
                    wMap.put(wOMSOrder.ID, wList.get(0));
                }
            }

            wResult.Result = wOrderList;
            wResult.CustomResult.put("OrderMap", wMap);
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> APS_OutApply(BMSEmployee wLoginUser, int wOrderID, List<String> wImagePathList,
                                               String wRemark) {
        ServiceResult<Integer> wResult = new ServiceResult<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            OMSOrder wOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wOrderID, wErrorCode);
            if (wOrder == null || wOrder.ID <= 0) {
                wResult.FaultCode += RetCode.SERVER_RST_ERROR_OUT;
                return wResult;
            }

            if (wOrder.Status == OMSOrderStatus.Repairing.getValue()) {
                wResult.FaultCode += "提示：该订单未竣工确认!";
                return wResult;
            }

            // ①判断是否是非线上车
            boolean wFlag = OMSOrderDAO.getInstance().IsOffLineBoarding(wLoginUser, wOrderID, wErrorCode);
            if (wFlag) {
                if (!IsInPlant(wLoginUser, wOrder)) {
                    wResult.FaultCode += StringUtils.Format("提示：【{0}】该车不在厂线上，无法出厂!", wOrder.PartNo);
                    return wResult;
                }

                OutPlantOffLine(wLoginUser, wImagePathList, wRemark, wOrder);

                return wResult;
            }

            List<SFCOrderForm> wFormList = SFCOrderFormDAO.getInstance().SelectList(wLoginUser, -1, wOrder.ID, "", 2,
                    null, wErrorCode);
            if (wFormList != null && wFormList.size() > 0) {
                wResult.FaultCode += "提示：该订单已申请出厂!";
                return wResult;
            }

            // 触发普查工位的日计划
            List<FPCPart> wOutFPartList = FMCServiceImpl.getInstance()
                    .FPC_QueryPartList(wLoginUser, -1, -1, -1, FPCPartTypes.OutFactory.getValue()).List(FPCPart.class);
            if (wOutFPartList == null || wOutFPartList.size() <= 0) {
                wResult.FaultCode += "提示：普查工位未设置!";
                return wResult;
            }

            int wShiftID = MESServer.MES_QueryShiftID(wLoginUser.CompanyID, Calendar.getInstance(), APSShiftPeriod.Day,
                    FMCShiftLevel.Day, 0);
            for (FPCPart wFPCPart : wOutFPartList) {
                List<Integer> wStepIDList = APSUtils.getInstance().FMC_QueryStepIDList(wLoginUser, wOrder.LineID,
                        wFPCPart.ID, wOrder.ProductID);
                if (wStepIDList == null || wStepIDList.size() <= 0) {
                    wResult.FaultCode += StringUtils.Format("提示：【{0}】工位下无工序!", wFPCPart.Name);
                    return wResult;
                }

                APSTaskStep wAPSTaskStep;
                for (Integer wStepID : wStepIDList) {
                    wAPSTaskStep = new APSTaskStep();
                    wAPSTaskStep.ID = 0;
                    wAPSTaskStep.Active = 1;
                    wAPSTaskStep.CreateTime = Calendar.getInstance();
                    wAPSTaskStep.LineID = wOrder.LineID;
                    wAPSTaskStep.OrderID = wOrder.ID;
                    wAPSTaskStep.PartID = wFPCPart.ID;
                    wAPSTaskStep.PartNo = wOrder.PartNo;
                    wAPSTaskStep.ProductNo = wOrder.ProductNo;
                    wAPSTaskStep.ShiftID = wShiftID;
                    wAPSTaskStep.Status = APSTaskStatus.Issued.getValue();
                    wAPSTaskStep.StepID = wStepID;
                    wAPSTaskStep.IsDispatched = false;
                    APSTaskStepDAO.getInstance().Update(wLoginUser, wAPSTaskStep, wErrorCode);
                }
            }

            // 生成出厂申请单
            SFCOrderForm wSFCOrderForm = new SFCOrderForm();
            wSFCOrderForm.CreateID = wLoginUser.ID;
            wSFCOrderForm.CreateTime = Calendar.getInstance();
            wSFCOrderForm.ID = 0;
            wSFCOrderForm.Type = 2;
            wSFCOrderForm.OrderID = wOrder.ID;
            wSFCOrderForm.OrderNo = wOrder.OrderNo;
            wSFCOrderForm.PartNo = wOrder.PartNo;
            wSFCOrderForm.Status = 1;
            if (wImagePathList != null && wImagePathList.size() > 0) {
                wSFCOrderForm.ImagePathList = wImagePathList;
            }
            if (StringUtils.isNotEmpty(wRemark)) {
                wSFCOrderForm.Remark = wRemark;
            }
            wResult.Result = SFCOrderFormDAO.getInstance().Update(wLoginUser, wSFCOrderForm, wErrorCode);

            // 修改订单的状态为待出厂普查
            wOrder.Status = OMSOrderStatus.ToOutChcek.getValue();
            OMSOrderDAO.getInstance().Update(BaseDAO.SysAdmin, wOrder, wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    /**
     * 非线上车直接出厂
     */
    private void OutPlantOffLine(BMSEmployee wLoginUser, List<String> wImagePathList, String wRemark,
                                 OMSOrder wOrder) {
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            // 生成出厂申请单
            SFCOrderForm wSFCOrderForm = new SFCOrderForm();

            wSFCOrderForm.CreateID = wLoginUser.ID;
            wSFCOrderForm.CreateTime = Calendar.getInstance();
            wSFCOrderForm.ID = 0;
            wSFCOrderForm.Type = 2;
            wSFCOrderForm.OrderID = wOrder.ID;
            wSFCOrderForm.OrderNo = wOrder.OrderNo;
            wSFCOrderForm.PartNo = wOrder.PartNo;
            wSFCOrderForm.Status = 2;
            wSFCOrderForm.ConfirmID = wLoginUser.ID;
            wSFCOrderForm.ConfirmTime = Calendar.getInstance();
            if (wImagePathList != null && wImagePathList.size() > 0) {
                wSFCOrderForm.ImagePathList = wImagePathList;
            }
            if (StringUtils.isNotEmpty(wRemark)) {
                wSFCOrderForm.Remark = wRemark;
            }

            SFCOrderFormDAO.getInstance().Update(wLoginUser, wSFCOrderForm, wErrorCode);

            // 修改订单的状态为待出厂普查
            wOrder.Status = OMSOrderStatus.CarSended.getValue();
            wOrder.RealSendDate = Calendar.getInstance();
            OMSOrderDAO.getInstance().Update(BaseDAO.SysAdmin, wOrder, wErrorCode);

            // 清掉台位上的车(待出厂)
            OMSOrderDAO.getInstance().ClearCar(wLoginUser, wOrder);

            // 推送订单到SAP
            String wFlag = Configuration.readConfigString("isSendSAP", "config/config");
            if (wFlag.equals("1")) {
                SendToSAP(wOrder);
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    @Override
    public ServiceResult<Integer> APS_OutConfirm(BMSEmployee wLoginUser, int wOrderID) {
        ServiceResult<Integer> wResult = new ServiceResult<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            OMSOrder wOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wOrderID, wErrorCode);
            if (wOrder == null || wOrder.ID <= 0) {
                wResult.FaultCode += RetCode.SERVER_RST_ERROR_OUT;
                return wResult;
            }

            if (wOrder.Status == OMSOrderStatus.Repairing.getValue()) {
                wResult.FaultCode += "提示：该订单未竣工确认!";
                return wResult;
            }

            List<SFCOrderForm> wFormList = SFCOrderFormDAO.getInstance().SelectList(wLoginUser, -1, wOrder.ID, "", 2,
                    null, wErrorCode);
            if (wFormList == null || wFormList.size() <= 0) {
                wResult.FaultCode += "提示：该订单的出厂申请单缺失!";
                return wResult;
            }

            // 修改出厂申请单的状态
            SFCOrderForm wSFCOrderForm = wFormList.get(0);
            wSFCOrderForm.ConfirmID = wLoginUser.ID;
            wSFCOrderForm.ConfirmTime = Calendar.getInstance();
            wSFCOrderForm.Status = 2;
            SFCOrderFormDAO.getInstance().Update(wLoginUser, wSFCOrderForm, wErrorCode);
            // 修改订单的状态
            wOrder.RealSendDate = Calendar.getInstance();
            wOrder.Status = OMSOrderStatus.CarSended.getValue();
            OMSOrderDAO.getInstance().Update(BaseDAO.SysAdmin, wOrder, wErrorCode);

            // 清掉台位上的车(待出厂)
            OMSOrderDAO.getInstance().ClearCar(wLoginUser, wOrder);

            // 推送订单到SAP
            String wFlag = Configuration.readConfigString("isSendSAP", "config/config");
            if (wFlag.equals("1")) {
                SendToSAP(wOrder);
            }
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    /**
     * 推送给SAP
     */
    private void SendToSAP(OMSOrder wOrder) {
        try {
            SimpleDateFormat wSDF = new SimpleDateFormat("yyyyMMdd");

            Calendar wTime = Calendar.getInstance();
            wTime.set(2010, 0, 1);

            List<OrderItem> wItemList = new ArrayList<>();

            OrderItem wItem = new OrderItem();
            wItem.PSPNR = wOrder.OrderNo;
            wItem.ZCHEX = wOrder.ProductNo;
            wItem.ZTCH = wOrder.PartNo.split("#")[1];
            wItem.ZRC_DATE = wSDF.format(wOrder.RealReceiveDate.getTime());

            if (wOrder.RealFinishDate.compareTo(wTime) <= 0) {
                wItem.ZWG_DATE = "";
            } else {
                wItem.ZWG_DATE = wSDF.format(wOrder.RealFinishDate.getTime());
            }

            wItemList.add(wItem);

            String wINPUT2 = JSON.toJSONString(wItemList);

            String wEndPoint = APSUtils.getInstance().GetSAPEndpoint();
            org.apache.axis.client.Service wService = new org.apache.axis.client.Service();
            Call wCall = (Call) wService.createCall();

            wCall.setUsername(APSUtils.getInstance().GetSAPUser());
            wCall.setPassword(APSUtils.getInstance().GetSAPPassword());

            wCall.setTargetEndpointAddress(wEndPoint);
            wCall.setOperationName(new QName("urn:sap-com:document:sap:rfc:functions", "ZIF_MES_INPUT_001"));// 调用的方法名
            wCall.addParameter("INPUT1", XMLType.XSD_STRING, javax.xml.rpc.ParameterMode.IN);
            wCall.addParameter("INPUT2", XMLType.XSD_STRING, javax.xml.rpc.ParameterMode.IN);
            wCall.setReturnType(XMLType.XSD_STRING); // 返回值类型：String

            String wReturn = (String) wCall.invoke(new Object[]{"02", wINPUT2});// 远程调用
            logger.info(wReturn);

            CalendarDAO.getInstance().WriteLogFile(wINPUT2 + "::" + wReturn, "台车WBS", wOrder, "");
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    /**
     * 判断车是否在厂线上
     */
    @SuppressWarnings("unused")
    private boolean IsInPlant(BMSEmployee wLoginUser, OMSOrder wOrder) {
        boolean wResult = false;
        try {
            List<FMCWorkspace> wList = FMCServiceImpl.getInstance()
                    .FMC_GetFMCWorkspaceList(wLoginUser, -1, -1, "", -1, 1).List(FMCWorkspace.class);
            if (wList == null || wList.size() <= 0) {
                return false;
            }

            if (wList.stream().noneMatch(p -> p.PartNo.equals(wOrder.PartNo))) {
                return false;
            }

            FMCWorkspace wWorkSpace = wList.stream().filter(p -> p.PartNo.equals(wOrder.PartNo)).findFirst().get();
            List<LFSStoreHouse> wHouseList = LFSServiceImpl.getInstance().LFS_QueryStoreHouseList(wLoginUser)
                    .List(LFSStoreHouse.class);
            if (wHouseList == null || wHouseList.size() <= 0) {
                return false;
            }

            if (wHouseList.stream().noneMatch(p -> p.ID == wWorkSpace.ParentID)) {
                return false;
            }

            LFSStoreHouse wHouse = wHouseList.stream().filter(p -> p.ID == wWorkSpace.ParentID).findFirst().get();

            if (wHouse.Type == 2) {
                wResult = true;
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> APS_AutoSendMessageToApplyOutPlant(BMSEmployee wLoginUser) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            // 每日8-9点开始提示
            Calendar wTStart = Calendar.getInstance();
            wTStart.set(Calendar.HOUR_OF_DAY, 8);
            wTStart.set(Calendar.MINUTE, 0);
            wTStart.set(Calendar.SECOND, 0);
            Calendar wTEnd = Calendar.getInstance();
            wTEnd.set(Calendar.HOUR_OF_DAY, 9);
            wTEnd.set(Calendar.MINUTE, 0);
            wTEnd.set(Calendar.SECOND, 0);
            if (!(Calendar.getInstance().compareTo(wTStart) > 0 && Calendar.getInstance().compareTo(wTEnd) < 0)) {
                return wResult;
            }
            // ①查询出已完工订单列表
            List<OMSOrder> wOrderList = OMSOrderDAO.getInstance().SelectList(wLoginUser, -1, -1, "", -1, -1, -1, "", "",
                    1, new ArrayList<>(Collections.singletonList(OMSOrderStatus.FinishedWork.getValue())), null, null,
                    null,
                    null, wErrorCode);
            if (wOrderList == null || wOrderList.size() <= 0) {
                return wResult;
            }

            int wShiftID = MESServer.MES_QueryShiftID(wLoginUser.CompanyID, Calendar.getInstance(), APSShiftPeriod.Day,
                    FMCShiftLevel.Day, 0);

            // ②遍历订单查询该订单是否已发起出厂申请，若没有，查消息列表，若没有发送消息提示，发送消息提示给所有有权限申请出厂的人
            List<BFCMessage> wMessageList = null;
            List<BFCMessage> wNewList = new ArrayList<>();
            BFCMessage wBFCMessage = null;
            for (OMSOrder wOMSOrder : wOrderList) {
                if (wOMSOrder.PartNo.contains("XS") || wOMSOrder.PartNo.contains("GL")) {
                    continue;
                }

                wMessageList = CoreServiceImpl.getInstance()
                        .BFC_GetMessageList(wLoginUser, -1, BPMEventModule.OutPlantApply.getValue(),
                                BFCMessageType.Notify.getValue(), -1, wShiftID, null, null)
                        .List(BFCMessage.class);
                if (wMessageList != null && wMessageList.size() > 0
                        && wMessageList.stream().anyMatch(p -> p.MessageID == wOMSOrder.ID)) {
                    continue;
                }

                List<Integer> wUserIDList = GetNoticeUesrList(wLoginUser);

                for (int wUserID : wUserIDList) {
                    wBFCMessage = new BFCMessage();
                    wBFCMessage.Active = 0;
                    wBFCMessage.CompanyID = wLoginUser.CompanyID;
                    wBFCMessage.CreateTime = Calendar.getInstance();
                    wBFCMessage.EditTime = Calendar.getInstance();
                    wBFCMessage.ID = 0;
                    wBFCMessage.MessageID = wOMSOrder.ID;
                    wBFCMessage.MessageText = StringUtils.Format("提示：【{0}-{1}】该订单已竣工确认，可发起出厂申请!", wOMSOrder.OrderNo,
                            wOMSOrder.PartNo);
                    wBFCMessage.ModuleID = BPMEventModule.OutPlantApply.getValue();
                    wBFCMessage.ResponsorID = wUserID;
                    wBFCMessage.ShiftID = wShiftID;
                    wBFCMessage.Title = StringUtils.Format("提示：【{0}-{1}】出厂申请通知!", wOMSOrder.OrderNo, wOMSOrder.PartNo);
                    wBFCMessage.Type = BFCMessageType.Notify.getValue();
                    wNewList.add(wBFCMessage);
                }
            }
            // ④发送通知消息
            if (wNewList.size() > 0) {
                CoreServiceImpl.getInstance().BFC_UpdateMessageList(wLoginUser, wNewList);
            }
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    /**
     * 根据权限获取出厂申请通知人列表
     */
    private List<Integer> GetNoticeUesrList(BMSEmployee wLoginUser) {
        List<Integer> wResult = new ArrayList<>();
        try {
            // ①计划员
            List<BMSRoleItem> wUList = CoreServiceImpl.getInstance().BMS_UserAllByRoleID(wLoginUser, 1)
                    .List(BMSRoleItem.class);
            List<Integer> wList = wUList.stream().map(p -> p.FunctionID).distinct().collect(Collectors.toList());
            if (wList.size() > 0) {
                wResult.addAll(wList);
            }
            // ②工区主管
            List<BMSRoleItem> wUList1 = CoreServiceImpl.getInstance().BMS_UserAllByRoleID(wLoginUser, 3)
                    .List(BMSRoleItem.class);
            List<Integer> wList1 = wUList1.stream().map(p -> p.FunctionID).distinct().collect(Collectors.toList());
            if (wList1.size() > 0) {
                wResult.addAll(wList1);
            }
        } catch (Exception e) {
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<OMSOrder>> OMS_QueryInPlantList(BMSEmployee wLoginUser, int wType) {
        ServiceResult<List<OMSOrder>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            List<OMSOrder> wList = new ArrayList<>();

            if (wType == 1) {
                wList = OMSOrderDAO.getInstance().SelectList(wLoginUser, -1, -1, "", -1, -1, -1, "", "", 1,
                        StringUtils.parseListArgs(OMSOrderStatus.EnterFactoryed.getValue(),
                                OMSOrderStatus.Repairing.getValue(), OMSOrderStatus.FinishedWork.getValue(),
                                OMSOrderStatus.ToOutChcek.getValue(), OMSOrderStatus.ToOutConfirm.getValue()),
                        null, null, null, null, wErrorCode);

                wList.sort((o1, o2) -> o2.RealReceiveDate.compareTo(o1.RealReceiveDate));
            } else {
                wList = OMSOrderDAO.getInstance().SelectList(wLoginUser, -1, -1, "", -1, -1, -1, "", "", 1,
                        StringUtils.parseListArgs(OMSOrderStatus.ReceivedTelegraph.getValue()), null, null, null,
                        null,
                        wErrorCode);

                wList.sort((o1, o2) -> o2.PlanReceiveDate.compareTo(o1.PlanReceiveDate));
            }

            if (wList.size() <= 0) {
                wResult.CustomResult.put("OrderMap", new HashMap<Integer, SFCOrderForm>());
                return wResult;
            }

            Map<Integer, SFCOrderForm> wOrderMap = new HashMap<>();
            for (OMSOrder wOMSOrder : wList) {
                List<SFCOrderForm> wFormList = SFCOrderFormDAO.getInstance().SelectList(wLoginUser, -1, wOMSOrder.ID,
                        "", SFCOrderFormType.InConfirm.getValue(), null, wErrorCode);
                if (wFormList == null || wFormList.size() <= 0) {
                    continue;
                }
                wOrderMap.put(wOMSOrder.ID, wFormList.get(0));
            }
            wResult.Result = wList;
            wResult.CustomResult.put("OrderMap", wOrderMap);
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> OMS_InPlantConfirm(BMSEmployee wLoginUser, int wOrderID, List<String> wImagePathList,
                                                     String wRemark) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            OMSOrder wOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wOrderID, wErrorCode);
            if (wOrder == null || wOrder.ID <= 0) {
                wResult.FaultCode += RetCode.SERVER_RST_ERROR_OUT;
                return wResult;
            }

            if (wOrder.Status != OMSOrderStatus.ReceivedTelegraph.getValue()) {
                wResult.FaultCode += "提示：请选择状态为“已收电报”的订单!";
                return wResult;
            }

            // 验证当前台车绑定的bop是否有对应版本的当前标准BOM，若无，无法创建
            boolean wFlag = MSSBOMItemDAO.getInstance().JudgeIsHasCurrent(wLoginUser, wOrder.RouteID, wErrorCode);
            if (!wFlag) {
                wResult.FaultCode += StringUtils.Format("提示：【{0}】绑定的工艺BOP无对应版本的当前标准BOM!", wOrder.PartNo);
                return wResult;
            }

            String wNotDisplayProductChar = Configuration.readConfigString("NotDisplayProductChar", "config/config");
            List<String> wChartList = StringUtils.parseList(wNotDisplayProductChar.split(","));

            // 创建进厂确认单
            SFCOrderForm wSFCOrderForm = new SFCOrderForm(0, wOrderID, wOrder.OrderNo, wOrder.PartNo, wLoginUser.ID,
                    wLoginUser.Name, Calendar.getInstance(), wLoginUser.ID, wLoginUser.Name, Calendar.getInstance(), 2,
                    SFCOrderFormType.InConfirm.getValue(), wOrder.LineName, wOrder.ProductNo, wOrder.BureauSection);
            if (wImagePathList != null && wImagePathList.size() > 0) {
                wSFCOrderForm.ImagePathList = wImagePathList;
            }
            if (StringUtils.isNotEmpty(wRemark)) {
                wSFCOrderForm.Remark = wRemark;
            }
            wResult.Result = SFCOrderFormDAO.getInstance().Update(wLoginUser, wSFCOrderForm, wErrorCode);
            // 修改订单状态为已进场
            wOrder.Status = OMSOrderStatus.EnterFactoryed.getValue();
            wOrder.RealReceiveDate = Calendar.getInstance();
            OMSOrderDAO.getInstance().Update(wLoginUser, wOrder, wErrorCode);

            // 将车绑定到厂线上(分多节情况)
            if (!wOrder.ProductNo.contains("XS") && wOrder.CustomerID != 43
                    && wChartList.stream().noneMatch(p -> wOrder.ProductNo.contains(p))) {
                List<MTCSectionInfo> wSectionList = WDWServiceImpl.getInstance()
                        .MTC_QuerySectionInfoList(wLoginUser, wOrder.ProductID).List(MTCSectionInfo.class);
                if (wSectionList != null && wSectionList.size() > 1) {
                    for (MTCSectionInfo wSectionInfo : wSectionList) {
                        String wPNo = StringUtils.Format("{0}-{1}", wOrder.PartNo, wSectionInfo.Name);

                        WDWServiceImpl.getInstance().WDW_BindCarToPlant(wLoginUser, wPNo);
                    }
                } else {
                    WDWServiceImpl.getInstance().WDW_BindCarToPlant(wLoginUser, wOrder.PartNo);
                }
            }

            // 创建并推送台车BOM
            // 查询台车BOM创建日志，若存在，则不创建台车bom
            List<APSBOMLog> apsbomLogs = APSBOMLogDAO.getInstance().SelectList(wLoginUser, -1, -1, -1, -1, wOrderID,
                    -1, null, null, wErrorCode);
            if (apsbomLogs.size() == 0) {
                ExecutorService wES = Executors.newFixedThreadPool(1);
                wES.submit(() -> APSServiceImpl.getInstance().APS_CreateBomItemByOrder(BaseDAO.SysAdmin, wOrderID));
                wES.shutdown();
            }

            // 修改订单的工艺路线为最新的
            ExecutorService wES2 = Executors.newFixedThreadPool(1);
            wES2.submit(() -> UpdateRoute(wLoginUser, new ArrayList<>(Collections.singletonList(wOrder))));
            wES2.shutdown();
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    /**
     * 工位返修频率提示
     */
    @Override
    public ServiceResult<Integer> APS_StationRepairFrequencyTip(BMSEmployee wLoginUser) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            // 每日8-9点开始提示
            Calendar wTStart = Calendar.getInstance();
            wTStart.set(Calendar.HOUR_OF_DAY, 8);
            wTStart.set(Calendar.MINUTE, 0);
            wTStart.set(Calendar.SECOND, 0);
            Calendar wTEnd = Calendar.getInstance();
            wTEnd.set(Calendar.HOUR_OF_DAY, 9);
            wTEnd.set(Calendar.MINUTE, 0);
            wTEnd.set(Calendar.SECOND, 0);
            if (!(Calendar.getInstance().compareTo(wTStart) > 0 && Calendar.getInstance().compareTo(wTEnd) < 0)) {
                return wResult;
            }
            // ①查询出所有下达的、开工的且激活的工位计划
            List<APSTaskPart> wAllToDoList = APSTaskPartDAO.getInstance().SelectList(wLoginUser, -1, -1, -1, -1, -1, 1,
                    APSShiftPeriod.Week.getValue(),
                    new ArrayList<>(
                            Arrays.asList(APSTaskStatus.Issued.getValue(), APSTaskStatus.Started.getValue())),
                    -1, null, null, wErrorCode);
            if (wAllToDoList.size() <= 0) {
                return wResult;
            }
            // ②去除开始时间大于明日的工位计划
            Calendar wTomTime = Calendar.getInstance();
            wTomTime.add(Calendar.DATE, 1);
            wTomTime.set(Calendar.HOUR_OF_DAY, 23);
            wTomTime.set(Calendar.MINUTE, 59);
            wTomTime.set(Calendar.SECOND, 59);
            wAllToDoList.removeIf(p -> p.StartTime.compareTo(wTomTime) > 0);
            // ③去除重复的工位计划
            wAllToDoList = new ArrayList<>(wAllToDoList.stream()
                    .collect(Collectors.toMap(APSTaskPart::getID, account -> account, (k1, k2) -> k2)).values());
            List<BFCMessage> wMessageList = new ArrayList<>();
            BFCMessage wMessage = null;
            // APS
            int wShiftID = MESServer.MES_QueryShiftID(wLoginUser.CompanyID, Calendar.getInstance(), APSShiftPeriod.Day,
                    FMCShiftLevel.Day, 0);
            // ④遍历工位计划，通过工位、车型、修程获取返修频率
            for (APSTaskPart wAPSTaskPart : wAllToDoList) {
                // 判断此工位任务今日是否已发送了消息，若发送了消息，continue
                List<BFCMessage> wTempMessageList = CoreServiceImpl.getInstance()
                        .BFC_GetMessageList(wLoginUser, -1, BPMEventModule.StationTip.getValue(),
                                BFCMessageType.Notify.getValue(), -1, wShiftID, null, null)
                        .List(BFCMessage.class);
                if (wTempMessageList != null && wTempMessageList.size() > 0
                        && wTempMessageList.stream().anyMatch(p -> p.MessageID == wAPSTaskPart.ID)) {
                    continue;
                }

                Map<String, Integer> wRepairMap = WDWServiceImpl.getInstance().RRO_QueryItemTaskList(wLoginUser,
                                APSConstans.GetFPCProducID(wAPSTaskPart.ProductNo), wAPSTaskPart.LineID,
                                wAPSTaskPart.PartID, 5)
                        .Info(Map.class);
                if (wRepairMap == null || wRepairMap.size() <= 0) {
                    continue;
                }
                // ⑤根据工位获取工区
                if (APSConstans.GetLFSWorkAreaStationList().values().stream()
                        .anyMatch(p -> p.StationID == wAPSTaskPart.PartID)) {
                    int wAreaID = APSConstans.GetLFSWorkAreaStationList().values().stream()
                            .filter(p -> p.StationID == wAPSTaskPart.PartID).findFirst().get().WorkAreaID;
                    if (wAreaID <= 0) {
                        continue;
                    }
                    // ⑥根据工区获取工区主管
                    if (APSConstans.GetLFSWorkAreaCheckerList().stream().anyMatch(
                            p -> p.WorkAreaID == wAreaID && p.LeaderIDList != null && p.LeaderIDList.size() > 0)) {
                        List<Integer> wLeaderList = new ArrayList<>();
                        List<LFSWorkAreaChecker> wLFSCheckerList = APSConstans
                                .GetLFSWorkAreaCheckerList().stream().filter(p -> p.WorkAreaID == wAreaID
                                        && p.LeaderIDList != null && p.LeaderIDList.size() > 0)
                                .collect(Collectors.toList());
                        for (LFSWorkAreaChecker wLFSWorkAreaChecker : wLFSCheckerList) {
                            wLeaderList.addAll(wLFSWorkAreaChecker.LeaderIDList);
                        }
                        wLeaderList = wLeaderList.stream().distinct().collect(Collectors.toList());
                        if (wLeaderList.size() <= 0) {
                            continue;
                        }
                        // ⑦创建发送给工区主管的通知消息
                        for (Integer wLeaderID : wLeaderList) {
                            wMessage = new BFCMessage();
                            wMessage.Active = 0;
                            wMessage.CompanyID = 0;
                            wMessage.CreateTime = Calendar.getInstance();
                            wMessage.EditTime = Calendar.getInstance();
                            wMessage.ID = 0;
                            wMessage.MessageID = wAPSTaskPart.ID;
                            wMessage.Title = StringUtils.Format("【{0}】【{1}】工位 以往返修项频率提示 ",
                                    BPMEventModule.StationTip.getLable(),
                                    APSConstans.GetFPCPartName(wAPSTaskPart.PartID));
                            wMessage.MessageText = this.GetMessageText(wRepairMap, wAPSTaskPart);
                            wMessage.ModuleID = BPMEventModule.StationTip.getValue();
                            wMessage.ResponsorID = wLeaderID;
                            wMessage.ShiftID = wShiftID;
                            wMessage.StationID = wAPSTaskPart.PartID;
                            wMessage.Type = BFCMessageType.Notify.getValue();
                            wMessageList.add(wMessage);
                        }
                    }
                }
            }
            // ⑧批量发送通知消息
            CoreServiceImpl.getInstance().BFC_UpdateMessageList(wLoginUser, wMessageList);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    private String GetMessageText(Map<String, Integer> wRepairMap, APSTaskPart wAPSTaskPart) {
        String wResult = "";
        try {
            if (wRepairMap == null || wRepairMap.size() <= 0) {
                wRepairMap = new HashMap<>();
            }

            StringBuilder wSB = new StringBuilder();
            wSB.append(StringUtils.Format("【{0}】-【{1}】-【{2}】以往返修项频率：",
                    wAPSTaskPart.LineName, wAPSTaskPart.ProductNo, wAPSTaskPart.PartName));
            for (String wContent : wRepairMap.keySet()) {
                if (StringUtils.isEmpty(wContent)) {
                    continue;
                }
                wSB.append(StringUtils.Format("返修项：【{0}】--频次：【{1}】    ",
                        wContent, wRepairMap.get(wContent)));
            }
            wResult = wSB.toString();
        } catch (Exception e) {
            logger.error(e.toString());
        }
        return wResult;
    }

    public ServiceResult<List<APSTaskPart>> APS_QueryCompareList(BMSEmployee wLoginUser, List<Integer> wOrderIDList) {
        ServiceResult<List<APSTaskPart>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            if (wOrderIDList == null || wOrderIDList.size() <= 0) {
                wResult.FaultCode += "提示：订单不能为空!";
                return wResult;
            }

            List<APSTaskPart> wTaskPartList = APSTaskPartDAO.getInstance().SelectListByOrderIDList(wLoginUser,
                    APSShiftPeriod.Week.getValue(), null, wOrderIDList, wErrorCode);

            List<APSTaskPart> wMonthTaskPartList = APSTaskPartDAO.getInstance().SelectListByOrderIDList(wLoginUser,
                    APSShiftPeriod.Month.getValue(), null, wOrderIDList, wErrorCode);

            for (APSTaskPart apsTaskPart : wTaskPartList) {
                if (apsTaskPart.Active != 1)
                    continue;
                for (APSTaskPart wMonthTaskPart : wMonthTaskPartList) {
                    if (wMonthTaskPart.Active != 1)
                        continue;
                    if (apsTaskPart.OrderID != wMonthTaskPart.OrderID || apsTaskPart.PartID != wMonthTaskPart.PartID) {
                        continue;
                    }

                    apsTaskPart.StartTime = wMonthTaskPart.StartTime;
                    apsTaskPart.EndTime = wMonthTaskPart.EndTime;
                }
            }

            Map<Integer, List<FPCRoutePart>> wRoutePartListMap = new HashMap<>();

            List<OMSOrder> wOrderList = OMSOrderDAO.getInstance().SelectListByIDList(wLoginUser, wOrderIDList,
                    wErrorCode);
            List<FPCRoutePart> wPartList = null;
            for (OMSOrder wOMSOrder : wOrderList) {

                if (wRoutePartListMap.containsKey(wOMSOrder.RouteID))
                    continue;
                wPartList = CoreServiceImpl.getInstance().FPC_QueryRoutePartList(wLoginUser, wOMSOrder.RouteID)
                        .List(FPCRoutePart.class);
                if (wPartList != null && wPartList.size() > 0) {
                    wRoutePartListMap.put(wOMSOrder.RouteID, wPartList);
                }
            }

            wResult.CustomResult.put("LineID", wOrderList.get(0).LineID);

            int wFlag = 1;
            int wOrderFlag = 1;
            List<APSTaskPart> wTreeList = new ArrayList<>();

            List<FPCRoutePart> wRoutePartList = new ArrayList<>();
            for (int i : wRoutePartListMap.keySet()) {
                wRoutePartList.addAll(wRoutePartListMap.get(i));
            }

            List<LFSWorkAreaStation> wWorkAreaStationList = new ArrayList<>(APSConstans
                    .GetLFSWorkAreaStationList().values());
            wWorkAreaStationList.removeIf(p -> wRoutePartList.stream().noneMatch(q -> q.PartID == p.StationID));
            wWorkAreaStationList.removeIf(p -> wTaskPartList.stream().noneMatch(q -> q.PartID == p.StationID));

            wWorkAreaStationList.sort(Comparator.comparing(LFSWorkAreaStation::getOrderNum));

            for (LFSWorkAreaStation wItem : wWorkAreaStationList) {

                APSTaskPart wAPSTaskPart = new APSTaskPart();
                wAPSTaskPart.PartID = wItem.StationID;
                wAPSTaskPart.PartOrder = wOrderFlag++;
                wAPSTaskPart.PartName = APSConstans.GetFPCPartName(wItem.StationID);

                wAPSTaskPart.UniqueID = wFlag++;
                wTreeList.add(wAPSTaskPart);

                for (FMCLine wLine : APSConstans.GetFMCLineList().values()) {
                    if (wLine.Active != 1)
                        continue;
                    APSTaskPart wLinePart = new APSTaskPart();
                    wLinePart.UniqueID = wFlag++;
                    wLinePart.LineID = wLine.ID;
                    wLinePart.LineName = wLine.Name;
                    wAPSTaskPart.TaskPartList.add(wLinePart);

                    wLinePart.TaskPartList = wTaskPartList.stream()
                            .filter(p -> (p.PartID == wItem.StationID && p.LineID == wLine.ID))
                            .collect(Collectors.toList());
                    if (wLinePart.TaskPartList.size() > 0) {
                        for (APSTaskPart wItemPart : wLinePart.TaskPartList) {
                            wItemPart.UniqueID = wFlag++;
                            wItemPart.PartOrder = wAPSTaskPart.PartOrder;
                        }
                        continue;
                    }
                    wLinePart.TaskPartList = new ArrayList<>();
                    wLinePart.TaskPartList.add(new APSTaskPart());
                }
            }

            wResult.CustomResult.put("TreeList", wTreeList);
            Calendar wBaseTime = Calendar.getInstance();
            wBaseTime.set(2000, 0, 1);
            Calendar wStartTime = wBaseTime;
            Calendar wEndTime = wBaseTime;

            if (wTaskPartList.size() > 0) {
                wStartTime = wTaskPartList.stream().min(Comparator.comparing(APSTaskPart::getStartTime))
                        .get().StartTime;
                Calendar wTime1 = wTaskPartList.stream()
                        .max(Comparator.comparing(APSTaskPart::getEndTime)).get().getEndTime();
                Calendar wTime2 = wTaskPartList.stream()
                        .max(Comparator.comparing(APSTaskPart::getFinishWorkTime)).get().getEndTime();
                if (wTime1.compareTo(wTime2) > 0) {
                    wEndTime = wTime1;
                } else {
                    wEndTime = wTime2;
                }
            }
            wResult.CustomResult.put("StartTime", wStartTime);
            wResult.CustomResult.put("EndTime", wEndTime);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode = String.valueOf(wResult.FaultCode) + e;
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<String> APS_CheckIsMakedMonthPlan(BMSEmployee wLoginUser, List<OMSOrder> wOrderList) {
        ServiceResult<String> wResult = new ServiceResult<>();
        wResult.Result = "";
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            if (wOrderList == null || wOrderList.size() <= 0) {
                return wResult;
            }

            wResult.Result = APSTaskPartDAO.getInstance().APS_CheckIsMakedMonthPlan(wLoginUser,
                    wOrderList.stream().map(p -> p.ID).collect(Collectors.toList()), wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<String> APS_CheckIsAreaLeader(BMSEmployee wLoginUser) {
        ServiceResult<String> wResult = new ServiceResult<>();
        wResult.Result = "";
        try {
            if (APSConstans.GetLFSWorkAreaCheckerList().stream().noneMatch(p -> p.LeaderIDList != null
                    && p.LeaderIDList.size() > 0 && p.LeaderIDList.stream().anyMatch(q -> q == wLoginUser.ID))) {
                wResult.Result = "提示：您不是工区主管，无法制定日计划!";
                return wResult;
            }
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<APSTaskStep>> APS_QueryTaskStepListByTime(BMSEmployee wLoginUser, Calendar wStartTime,
                                                                        Calendar wEndTime) {
        ServiceResult<List<APSTaskStep>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            // ②获取登录者的工位列表
            List<Integer> wPartIDList = null;
            if (CoreServiceImpl.getInstance()
                    .BMS_CheckPowerByAuthorityID(wLoginUser.CompanyID, wLoginUser.ID, 501002, 0, 0)
                    .Info(Boolean.class)) {
                wPartIDList = new ArrayList<>();
            } else {
                // 工位ID集合
                wPartIDList = this.GetPartIDListByLoginUser(wLoginUser);
                if (wPartIDList == null || wPartIDList.size() <= 0) {
                    return wResult;
                }
            }

            // ⑤出厂检和终检任务
            wResult.Result.addAll(APSTaskStepDAO.getInstance().SelectQTList(wLoginUser, null, null,
                    new ArrayList<>(
                            Arrays.asList(APSTaskStatus.Issued.getValue(), APSTaskStatus.Started.getValue())),
                    wPartIDList, wErrorCode));
            wResult.Result.addAll(APSTaskStepDAO.getInstance().SelectQTList(wLoginUser, wStartTime, wEndTime,
                    new ArrayList<>(Collections.singletonList(APSTaskStatus.Done.getValue())), wPartIDList,
                    wErrorCode));

            // ③通过时间段和工位列表查询工位任务集合
            List<APSTaskPart> wTaskPartList = APSTaskPartDAO.getInstance().SelectListByTime(wLoginUser, wPartIDList,
                    wStartTime, wEndTime, wErrorCode);
            if (wTaskPartList != null && wTaskPartList.size() > 0) {
                // ④通过工位任务集合查询工序任务集合
                wResult.Result.addAll(APSTaskStepDAO.getInstance().SelectListByTaskPartIDList(wLoginUser,
                        wTaskPartList.stream().map(p -> p.ID).collect(Collectors.toList()), wErrorCode));
            }

            if (wResult.Result.size() <= 0) {
                return wResult;
            }

            // ⑥去重
            wResult.Result = new ArrayList<>(wResult.Result.stream()
                    .collect(Collectors.toMap(APSTaskStep::getID, account -> account, (k1, k2) -> k2)).values());

            /*
             * 默认人员返回(没派工记录时默认返回)
             */
            List<SFCTaskStep> wList = null;
            Map<Integer, List<Integer>> wPersonMap = SFCServiceImpl.getInstance().SFC_QueryStepPersonMap(wLoginUser,
                    wResult.Result).Result;

            List<Integer> wAPSTaskstepIDList = wResult.Result.stream().map(p -> p.ID).collect(Collectors.toList());
            wList = SFCTaskStepDAO.getInstance().SelectListByTaskStepIDList(wLoginUser, wAPSTaskstepIDList,
                    SFCTaskStepType.Step.getValue(), wErrorCode);

            for (APSTaskStep wAPSTaskStep : wResult.Result) {
                List<SFCTaskStep> wTempList = wList.stream().filter(p -> p.TaskStepID == wAPSTaskStep.ID)
                        .collect(Collectors.toList());

                if (wAPSTaskStep.OperatorList != null && wAPSTaskStep.OperatorList.size() > 0) {
                    wAPSTaskStep.Operators = GetUserNames(wAPSTaskStep.OperatorList);
                    continue;
                }

                if (wTempList.size() > 0) {
                    wAPSTaskStep.OperatorList = wTempList.stream().map(p -> p.OperatorID).collect(Collectors.toList());
                    continue;
                }

                if (!wPersonMap.containsKey(wAPSTaskStep.ID)) {
                    continue;
                }
                wAPSTaskStep.OperatorList = wPersonMap.get(wAPSTaskStep.ID);
                wAPSTaskStep.Operators = GetUserNames(wPersonMap.get(wAPSTaskStep.ID));
            }

            if (wResult.Result.size() > 0) {
                wResult.Result.removeIf(p -> p.Active != 1);
            }
        } catch (Exception e) {
            logger.error(StringUtils.Format("{0} {1} ex：{2}", "APSServiceImpl", "APS_QueryTaskStepListByMonitorID",
                    e.toString()));
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<APSTaskStep>> APS_QueryTaskStepByConditions(BMSEmployee wLoginUser, Calendar wStartTime,
                                                                          Calendar wEndTime, int wAreaID, int wLineID, int wPartID) {
        ServiceResult<List<APSTaskStep>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            List<APSTaskStep> wStepTaskList = APSTaskStepDAO.getInstance().SelectList(wLoginUser, -1, -1, -1, -1, -1,
                    wLineID, wPartID, -1, -1, 1, null, wStartTime, wEndTime, null, wErrorCode);

            // 工区工位
            if (wAreaID > 0) {
                List<LFSWorkAreaStation> wAreaStationList = APSConstans.GetLFSWorkAreaStationList().values().stream()
                        .filter(p -> p.WorkAreaID == wAreaID).collect(Collectors.toList());
                wStepTaskList = wStepTaskList.stream()
                        .filter(p -> wAreaStationList.stream().anyMatch(q -> q.StationID == p.PartID))
                        .collect(Collectors.toList());
            }

            // 工艺数据
            List<FPCRoutePart> wFPCRoutePartList = FMCServiceImpl.getInstance()
                    .FPC_QueryRoutePartListByRouteID(BaseDAO.SysAdmin, 0).List(FPCRoutePart.class);
            List<FPCRoutePartPoint> wFPCRoutePartPointList = FMCServiceImpl.getInstance()
                    .FPC_QueryRoutePartPointListByRouteID(BaseDAO.SysAdmin, 0, 0).List(FPCRoutePartPoint.class);

            ServiceResult<List<OMSOrder>> wOrderResult = this.GetOrderListAndTaskPartListWithWholeTaskStep(wLoginUser,
                    wStepTaskList, wFPCRoutePartList, wFPCRoutePartPointList);

            wResult.Result = (List<APSTaskStep>) wOrderResult.CustomResult.get("TaskStepList");
            wResult.CustomResult.put("OrderList", wOrderResult.Result);
            wResult.CustomResult.put("TaskPartList", wOrderResult.CustomResult.get("TaskPartList"));
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<SFCTaskStepInfo>> APS_QuerySFCTaskStepInfoList(BMSEmployee wLoginUser,
                                                                             List<APSTaskStep> wList) {
        ServiceResult<List<SFCTaskStepInfo>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            if (wList == null || wList.size() <= 0) {
                return wResult;
            }
            // 去重
            List<APSTaskStep> wDistinctList = new ArrayList<>(wList.stream()
                    .collect(Collectors.toMap(APSTaskStep::getID, account -> account, (k1, k2) -> k2)).values());
            // 工区工位列表
            List<LFSWorkAreaStation> wLFSWorkAreaStationList = new ArrayList<>(
                    APSConstans.GetLFSWorkAreaStationList().values());

            SFCTaskStepInfo wSFCTaskStepInfo = null;
            for (APSTaskStep wAPSTaskStep : wDistinctList) {
                wSFCTaskStepInfo = new SFCTaskStepInfo();
                wSFCTaskStepInfo.OrderID = wAPSTaskStep.OrderID;
                wSFCTaskStepInfo.OrderNo = wAPSTaskStep.OrderNo;
                wSFCTaskStepInfo.PartNo = wAPSTaskStep.PartNo;
                wSFCTaskStepInfo.StationID = wAPSTaskStep.PartID;
                wSFCTaskStepInfo.StationName = wAPSTaskStep.PartName;
                wSFCTaskStepInfo.ToDispatch = (int) wList.stream().filter(
                                p -> (p.OrderID == wAPSTaskStep.OrderID && p.PartID == wAPSTaskStep.PartID && !p.IsDispatched))
                        .count();
                wSFCTaskStepInfo.Dispatched = (int) wList.stream().filter(
                                p -> (p.OrderID == wAPSTaskStep.OrderID && p.PartID == wAPSTaskStep.PartID && p.IsDispatched))
                        .count();
                wSFCTaskStepInfo.Status = wSFCTaskStepInfo.ToDispatch == 0 ? 1 : 0;
                if (wLFSWorkAreaStationList.size() > 0
                        && wLFSWorkAreaStationList.stream().anyMatch(p -> p.StationID == wAPSTaskStep.PartID)) {
                    wSFCTaskStepInfo.OrderNum = wLFSWorkAreaStationList.stream()
                            .filter(p -> p.StationID == wAPSTaskStep.PartID).findFirst().get().OrderNum;
                }
                if (wResult.Result.stream()
                        .noneMatch(p -> p.OrderID == wAPSTaskStep.OrderID && p.StationID == wAPSTaskStep.PartID)) {
                    wResult.Result.add(wSFCTaskStepInfo);
                }
            }

            // 排序1、状态升序2、车号升序3、顺序升序
            if (wResult.Result.size() > 0) {
                // 排序
                wResult.Result.sort(Comparator.comparing(SFCTaskStepInfo::getStatus)
                        .thenComparing(SFCTaskStepInfo::getPartNo).thenComparing(SFCTaskStepInfo::getOrderNum));
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<APSDayPlanAuditBPM> APS_SubmitDayPlanAuditBPMTask(BMSEmployee wLoginUser,
                                                                           APSDayPlanAuditBPM wData) {
        ServiceResult<APSDayPlanAuditBPM> wResult = new ServiceResult<>();
        wResult.Result = new APSDayPlanAuditBPM();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            // ①判断输入数据的正确性
            if (wData == null || wData.ID <= 0) {
                return wResult;
            }
            // ②查询出所有子项

            List<APSTaskStep> wList = null;
            if (wData.AuditItemBPMList != null && wData.AuditItemBPMList.size() > 0) {
                wList = APSTaskStepDAO.getInstance().SelectListByIDList(wLoginUser, wData.AuditItemBPMList.stream()
                        .map(p -> p.APSTaskStepID).distinct().collect(Collectors.toList()), wErrorCode);
            }

            // ②若数据状态为“提交”，修改子项的状态为“待审批”，修改单据的状态为“待审批”
            if (wList != null && wList.size() > 0 && wData.Status == 1) {
                wList.forEach(p -> {
                    if (wData.AuditItemBPMList.stream().anyMatch(q -> q.Status == 1 && q.APSTaskStepID == p.ID)) {
                        p.Status = APSTaskBPMStatus.ToAudit.getValue();
                    } else {
                        APSDayPlanAuditItemBPM wAuditBPM = wData.AuditItemBPMList.stream()
                                .filter(q -> q.Status == 0 && q.APSTaskStepID == p.ID).findFirst().get();
                        p.Remark = new APSTaskRemark();
                        p.Remark.Remark = wAuditBPM.Remark;
                        p.Remark.SubimtTime = Calendar.getInstance();
                        p.RemarkList.add(p.Remark);
                    }
                    APSTaskStepDAO.getInstance().Update(wLoginUser, p, wErrorCode);
                });
            }
            // ③若数据状态为“已驳回”，修改子项的状态为“保存”，修改单据的状态“保存”
            else if (wList != null && wList.size() > 0 && wData.Status == 22) {
                wList.forEach(p -> {
                    if (wData.AuditItemBPMList.stream().anyMatch(q -> q.Status == 1 && q.APSTaskStepID == p.ID)) {
                        p.Status = APSTaskBPMStatus.Saved.getValue();
                        APSTaskStepDAO.getInstance().Update(wLoginUser, p, wErrorCode);
                    }
                });
                wData.StatusText = APSTaskBPMStatus.Rejected.getLable();
            }
            // 撤销
            else if (wList != null && wList.size() > 0 && wData.Status == 21) {
                wList.forEach(p -> {
                    if (wData.AuditItemBPMList.stream().anyMatch(q -> q.Status == 1 && q.APSTaskStepID == p.ID)) {
                        p.Status = APSTaskBPMStatus.Saved.getValue();
                        APSTaskStepDAO.getInstance().Update(wLoginUser, p, wErrorCode);
                    }
                });
                wData.StatusText = "已撤销";
            }
            // ⑤若数据状态为“已审批”，修改子项的状态为“已审批”，修改单据的状态为“已审批”
            else if (wList != null && wList.size() > 0 && wData.Status == 2) {
                wList.forEach(p -> {
                    if (wData.AuditItemBPMList.stream().anyMatch(q -> q.Status == 1 && q.APSTaskStepID == p.ID)) {
                        p.Status = APSTaskBPMStatus.Audited.getValue();
                        APSTaskStepDAO.getInstance().Update(wLoginUser, p, wErrorCode);
                    }
                });
            } else if (wList != null && wList.size() > 0 && wData.Status == 3) {
                wList.forEach(p -> {
                    if (wData.AuditItemBPMList.stream().anyMatch(q -> q.Status == 1 && q.APSTaskStepID == p.ID)) {
                        p.Status = APSTaskStatus.Issued.getValue();
                        p.ReadyTime = Calendar.getInstance();
                        APSTaskStepDAO.getInstance().Update(wLoginUser, p, wErrorCode);
                    }
                });
                wData.StatusText = "已下达";
            }

            if (wData.Status == 20 || wData.Status == 3) {
                if (wData.Status == 3) {
                    wData.Status = 20;
                }
                wData.StatusText = "已下达";
            }

            // ⑥保存单据
            wResult.Result = (APSDayPlanAuditBPM) APSDayPlanAuditBPMDAO.getInstance().BPM_UpdateTask(wLoginUser, wData,
                    wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<APSDayPlanAuditBPM> APS_QueryDefaultDayPlanAuditBPMTask(BMSEmployee wLoginUser, int wEventID) {
        ServiceResult<APSDayPlanAuditBPM> wResult = new ServiceResult<>();
        wResult.Result = new APSDayPlanAuditBPM();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            List<APSDayPlanAuditBPM> wList = APSDayPlanAuditBPMDAO.getInstance().SelectList(wLoginUser, -1, "",
                    wLoginUser.ID, null, -1, -1,
                    new ArrayList<>(Collections.singletonList(APSTaskBPMStatus.Default.getValue())), null, null,
                    wErrorCode);
            if (wList != null && wList.size() > 0) {
                wResult.Result = wList.get(0);
                wResult.Result.CreateTime = Calendar.getInstance();
                wResult.Result.SubmitTime = Calendar.getInstance();
                int wShiftID = MESServer.MES_QueryShiftID(wLoginUser.CompanyID, Calendar.getInstance(),
                        APSShiftPeriod.Day, FMCShiftLevel.Day, 0);
                wResult.Result.ShiftDate = Calendar.getInstance();
                wResult.Result.ShiftID = wShiftID;

                wResult.Result.AreaID = APSConstans.GetLFSWorkAreaCheckerList().stream()
                        .filter(p -> p.LeaderIDList != null && p.LeaderIDList.size() > 0
                                && p.LeaderIDList.stream().anyMatch(q -> q == wLoginUser.ID))
                        .findFirst().get().WorkAreaID;
                wResult.Result.AreaName = APSConstans.GetBMSDepartmentName(wResult.Result.AreaID);
                wResult.Result.UpFlowName = APSConstans.GetBMSEmployeeName(wLoginUser.ID);
            }
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public synchronized ServiceResult<APSDayPlanAuditBPM> APS_CreateDayPlanAuditBPMTask(BMSEmployee wLoginUser,
                                                                                        BPMEventModule wEventID) {
        ServiceResult<APSDayPlanAuditBPM> wResult = new ServiceResult<>();
        wResult.Result = new APSDayPlanAuditBPM();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            int wShiftID = MESServer.MES_QueryShiftID(wLoginUser.CompanyID, Calendar.getInstance(), APSShiftPeriod.Day,
                    FMCShiftLevel.Day, 0);

            APSDayPlanAuditBPM wAPSDayPlanAuditBPM = new APSDayPlanAuditBPM();
            wAPSDayPlanAuditBPM.Code = APSDayPlanAuditBPMDAO.getInstance().GetNewCode(wLoginUser, wErrorCode);
            wAPSDayPlanAuditBPM.ShiftID = wShiftID;
            wAPSDayPlanAuditBPM.ShiftDate = Calendar.getInstance();
            wAPSDayPlanAuditBPM.ID = 0;
            wAPSDayPlanAuditBPM.FlowType = BPMEventModule.SCDayAudit.getValue();
            wAPSDayPlanAuditBPM.UpFlowID = wLoginUser.ID;
            wAPSDayPlanAuditBPM.Status = APSTaskBPMStatus.Default.getValue();
            wAPSDayPlanAuditBPM.StatusText = "";
            wAPSDayPlanAuditBPM.CreateTime = Calendar.getInstance();
            wAPSDayPlanAuditBPM.SubmitTime = Calendar.getInstance();

            // 赋值AreaID
            if (APSConstans.GetLFSWorkAreaCheckerList().stream().anyMatch(p -> p.LeaderIDList != null
                    && p.LeaderIDList.size() > 0 && p.LeaderIDList.stream().anyMatch(q -> q == wLoginUser.ID))) {
                wAPSDayPlanAuditBPM.AreaID = APSConstans.GetLFSWorkAreaCheckerList().stream()
                        .filter(p -> p.LeaderIDList != null && p.LeaderIDList.size() > 0
                                && p.LeaderIDList.stream().anyMatch(q -> q == wLoginUser.ID))
                        .findFirst().get().WorkAreaID;
                wAPSDayPlanAuditBPM.AreaName = APSConstans.GetBMSDepartmentName(wAPSDayPlanAuditBPM.AreaID);
                wAPSDayPlanAuditBPM.UpFlowName = APSConstans.GetBMSEmployeeName(wLoginUser.ID);
            }

            // 限制审批单的创建
            List<APSDayPlanAuditBPM> wList = APSDayPlanAuditBPMDAO.getInstance().SelectList(wLoginUser, -1, "", -1, "",
                    wAPSDayPlanAuditBPM.AreaID, -1, new ArrayList<>(Arrays.asList(1, 2, 3)), null, null,
                    wErrorCode);
            if (wList.size() > 0) {
                wResult.FaultCode += "提示：该工区有未完成的审批单，请完成后再次制定!";
                return wResult;
            }

            wResult.Result = (APSDayPlanAuditBPM) APSDayPlanAuditBPMDAO.getInstance().BPM_UpdateTask(wLoginUser,
                    wAPSDayPlanAuditBPM, wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<APSDayPlanAuditBPM> APS_GetDayPlanAuditBPMTask(BMSEmployee wLoginUser, int wID) {
        ServiceResult<APSDayPlanAuditBPM> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            wResult.Result = (APSDayPlanAuditBPM) APSDayPlanAuditBPMDAO.getInstance().BPM_GetTaskInfo(wLoginUser, wID,
                    "", wErrorCode);
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<APSDayPlanAuditBPM>> APS_QueryDayPlanAuditBPMHistory(BMSEmployee wLoginUser, int wID,
                                                                                   String wCode, int wUpFlowID,
                                                                                   int wFollowerID, int wAreaID,
                                                                                   int wShiftID, Calendar wStartTime,
                                                                                   Calendar wEndTime) {
        ServiceResult<List<APSDayPlanAuditBPM>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            wResult.Result = APSDayPlanAuditBPMDAO.getInstance().SelectList(wLoginUser, wID, wCode, wUpFlowID,
                    String.valueOf(wFollowerID), wAreaID, wShiftID, null, wStartTime, wEndTime, wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<BPMTaskBase>> APS_QueryDayPlanAuditBPMEmployeeAll(BMSEmployee wLoginUser, int wTagTypes,
                                                                                Calendar wStartTime,
                                                                                Calendar wEndTime) {
        ServiceResult<List<BPMTaskBase>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            switch (TagTypes.getEnumType(wTagTypes)) {
                case Applicant:// 2发起
                    wResult.Result = APSDayPlanAuditBPMDAO.getInstance().BPM_GetSendTaskList(wLoginUser, wLoginUser.ID,
                            wStartTime, wEndTime, wErrorCode);
                    break;
                case Dispatcher:// 1待做
                    wResult.Result = APSDayPlanAuditBPMDAO.getInstance().BPM_GetUndoTaskList(wLoginUser, wLoginUser.ID,
                            wErrorCode);
                    break;
                case Approver:// 4已做
                    wResult.Result = APSDayPlanAuditBPMDAO.getInstance().BPM_GetDoneTaskList(wLoginUser, wLoginUser.ID,
                            wStartTime, wEndTime, wErrorCode);
                    break;
                default:
                    break;
            }

            if (wResult.Result.size() > 0) {
                wResult.Result = wResult.Result.stream().filter(p -> p.Status != 0).collect(Collectors.toList());
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<APSTaskStep>> APS_QueryDayPlanAuditItemDetails(BMSEmployee wLoginUser,
                                                                             int wAPSDayPlanAuditBPMID) {
        ServiceResult<List<APSTaskStep>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            APSDayPlanAuditBPM wItem = (APSDayPlanAuditBPM) APSDayPlanAuditBPMDAO.getInstance()
                    .BPM_GetTaskInfo(wLoginUser, wAPSDayPlanAuditBPMID, "", wErrorCode);
            if (wItem == null || wItem.ID <= 0 || wItem.AuditItemBPMList == null
                    || wItem.AuditItemBPMList.size() <= 0) {

                wResult.CustomResult.put("Info", wItem);
                wResult.CustomResult.put("PartList", new ArrayList<APSTaskPartDetails>());

                return wResult;
            }

            wResult.Result = APSTaskStepDAO.getInstance().SelectListByIDList(wLoginUser,
                    wItem.AuditItemBPMList.stream().map(p -> p.APSTaskStepID).distinct().collect(Collectors.toList()),
                    wErrorCode);

            // 提取订单
            List<Integer> wOrderIDList = wResult.Result.stream().map(p -> p.OrderID).distinct()
                    .collect(Collectors.toList());
            List<OMSOrder> wOList = OMSOrderDAO.getInstance().SelectListByIDList(wLoginUser, wOrderIDList, wErrorCode);
            // 订单排序
            // wOList.sort(Comparator.comparing(OMSOrder::getRealReceiveDate));
            wOList.sort(Comparator.comparing(OMSOrder::getERPID).thenComparing(OMSOrder::getRealReceiveDate));
            // 结果排序
            wResult.Result = OrderResultTaskStep(wOList, wResult.Result);

            // 提取工位信息
            List<APSTaskPartDetails> wDetailsList = new ArrayList<>();
            List<APSTaskPart> wTaskPartList = APSTaskPartDAO.getInstance().SelectListByIDList(wLoginUser,
                    wResult.Result.stream().map(p -> p.TaskPartID).distinct().collect(Collectors.toList()), wErrorCode);

            // 工位任务排序
            wTaskPartList = OrderTaskPartList(wOList, wTaskPartList);

            APSTaskPartDetails wAPSTaskPartDetails;
            for (APSTaskPart wAPSTaskPart : wTaskPartList) {
                // 工位详情
                wAPSTaskPartDetails = new APSTaskPartDetails();
                wAPSTaskPartDetails.APSTaskPart = wAPSTaskPart;

                List<APSTaskStep> wTaskStepList = wResult.Result.stream().filter(p -> p.TaskPartID == wAPSTaskPart.ID)
                        .collect(Collectors.toList());

                // 工序总数
                wAPSTaskPartDetails.StepSize = wTaskStepList.size();
                // 工序完成数
                wAPSTaskPartDetails.StepFinish = (int) wTaskStepList.stream()
                        .filter(p -> p.Status == APSTaskStatus.Done.getValue()).count();
                // 工序在制数
                wAPSTaskPartDetails.StepMaking = (int) wTaskStepList.stream()
                        .filter(p -> p.Status == APSTaskStatus.Submit.getValue()
                                || p.Status == APSTaskStatus.ToAudit.getValue()
                                || p.Status == APSTaskStatus.Audited.getValue())
                        .count();
                // 工序已排数
                wAPSTaskPartDetails.StepSchedule = (int) wTaskStepList.stream()
                        .filter(p -> p.Status == APSTaskStatus.Issued.getValue()
                                || p.Status == APSTaskStatus.Started.getValue()
                                || p.Status == APSTaskStatus.Done.getValue())
                        .count();

                if (APSConstans.GetLFSWorkAreaStationList().values().stream()
                        .anyMatch(p -> p.StationID == wAPSTaskPart.PartID && p.Active == 1)) {
                    wAPSTaskPartDetails.AreaID = APSConstans.GetLFSWorkAreaStationList().values().stream()
                            .filter(p -> p.StationID == wAPSTaskPart.PartID && p.Active == 1).findFirst()
                            .get().WorkAreaID;
                    wAPSTaskPartDetails.AreaName = APSConstans.GetBMSDepartmentName(wAPSTaskPartDetails.AreaID);
                }

                wDetailsList.add(wAPSTaskPartDetails);
            }

            wResult.CustomResult.put("Info", wItem);
            wResult.CustomResult.put("PartList", wDetailsList);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    /**
     * 排序
     */
    private List<APSTaskPart> OrderTaskPartList(List<OMSOrder> wOList, List<APSTaskPart> wTaskPartList) {
        List<APSTaskPart> wResult = new ArrayList<>();
        try {
            if (wTaskPartList == null || wTaskPartList.size() <= 0) {
                return wResult;
            }

            for (OMSOrder wOMSOrder : wOList) {
                List<APSTaskPart> wList = wTaskPartList.stream().filter(p -> p.OrderID == wOMSOrder.ID)
                        .collect(Collectors.toList());
                if (wList.size() > 0) {
                    wResult.addAll(wList);
                }
            }
        } catch (Exception e) {
            logger.error(e.toString());
        }
        return wResult;
    }

    /**
     * 排序
     */
    private List<APSTaskStep> OrderResultTaskStep(List<OMSOrder> wOList, List<APSTaskStep> wAPSTaskStepList) {
        List<APSTaskStep> wResult = new ArrayList<>();
        try {
            if (wAPSTaskStepList == null || wAPSTaskStepList.size() <= 0) {
                return wResult;
            }

            for (OMSOrder wOMSOrder : wOList) {
                List<APSTaskStep> wList = wAPSTaskStepList.stream().filter(p -> p.OrderID == wOMSOrder.ID)
                        .collect(Collectors.toList());
                if (wList.size() > 0) {
                    wResult.addAll(wList);
                }
            }
        } catch (Exception e) {
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<FPCRoute>> ASP_QueryRouteList(BMSEmployee wLoginUser, List<Integer> wRouteIDList,
                                                            Map<Integer, List<FPCRoutePart>> wRouteMap) {
        ServiceResult<List<FPCRoute>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            if (wRouteIDList == null || wRouteIDList.size() <= 0) {
                return wResult;
            }

            for (Integer wRouteID : wRouteIDList) {
                FPCRoute wRoute = FPCRouteDAO.getInstance().SelectByID(wLoginUser, wRouteID, wErrorCode);
                if (wRouteMap.containsKey(wRouteID)) {
                    wRoute.PartList = wRouteMap.get(wRouteID);
                } else {
                    wRoute.PartList = FMCServiceImpl.getInstance().FPC_QueryRoutePartListByRouteID(wLoginUser, wRouteID)
                            .List(FPCRoutePart.class);
                }
                wResult.Result.add(wRoute);
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<String> Export(BMSEmployee wLoginUser, String wVersionNo, String wSuffix, int wTaskPartID,
                                        int wAPSShiftPeriod) {
        ServiceResult<String> wResult = new ServiceResult<>();
        wResult.Result = "";
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            if (StringUtils.isEmpty(wVersionNo)) {
                wVersionNo = APSSchedulingVersionDAO.getInstance().GetVersonNo(wLoginUser, wTaskPartID, wErrorCode);
            }

            if (StringUtils.isEmpty(wVersionNo)) {
                wResult.FaultCode += "提示：参数错误!";
                return wResult;
            }

            APSSchedulingVersion wVersion = APSSchedulingVersionDAO.getInstance().SelectByVersionNo(wLoginUser,
                    wVersionNo, wErrorCode);

            int wYear = Calendar.getInstance().get(Calendar.YEAR);

            SimpleDateFormat wSimpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
            String wCurTime = wSimpleDateFormat.format(Calendar.getInstance().getTime());
            String wType = wAPSShiftPeriod == APSShiftPeriod.Month.getValue() ? "月" : "周";
            String wFileName = StringUtils.Format("{0}-{1}-{2}滚动计划.xls", String.valueOf(wYear), wCurTime, wType);
            String wDirePath = StringUtils.Format("{0}static/export/",
                    Constants.getConfigPath().replace("config/", ""));
            File wDirFile = new File(wDirePath);
            if (!wDirFile.exists()) {
                wDirFile.mkdirs();
            }
            String wFilePath = StringUtils.Format("{0}{1}", wDirePath, wFileName);
            File wNewFile = new File(wFilePath);
            wNewFile.createNewFile();
            List<List<String>> wSourceList = this.APS_GetSourceList(wLoginUser, wVersion, wSuffix);

            FileOutputStream wFileOutputStream = new FileOutputStream(wNewFile);
            ExcelUtil.APS_WriteScrollPlan(wSourceList, wFileOutputStream, wType);
            wResult.Result = StringUtils.Format("/{0}/export/{1}",
                    Configuration.readConfigString("project.name", "application"), wFileName);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    /**
     * 获取滚动计划数据源
     */
    private List<List<String>> APS_GetSourceList(BMSEmployee wLoginUser, APSSchedulingVersion wVersion,
                                                 String wSuffix) {
        List<List<String>> wResult = new ArrayList<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            // ①构造表头数据
            List<Integer> wShiftIDList = this.GetShiftIDs(wVersion);
            List<String> wHearderList = this.GetHeaderList(wVersion);
            wResult.add(wHearderList);
            // ②获取工位计划列表
            List<APSTaskPart> wTaskPartList = APSTaskPartDAO.getInstance().SelectListByIDList(wLoginUser,
                    wVersion.TaskPartIDList, null, wErrorCode);
            // ④根据工区工位表，排序工位
            List<LFSWorkAreaStation> wASList = APSConstans.GetLFSWorkAreaStationList().values().stream()
                    .filter(p -> p.Active == 1).sorted(Comparator.comparing(LFSWorkAreaStation::getOrderNum))
                    .collect(Collectors.toList());

            // 获取工艺路线列表
            List<Integer> wOrderIDList = wTaskPartList.stream().map(p -> p.OrderID).collect(Collectors.toList());
            List<OMSOrder> wOrderList = OMSOrderDAO.getInstance().SelectListByIDList(wLoginUser, wOrderIDList,
                    wErrorCode);
            List<Integer> wRouteIDList = wOrderList.stream().map(p -> p.RouteID).distinct()
                    .collect(Collectors.toList());

            List<FPCRoutePart> wRoutePartList = new ArrayList<>();
            for (Integer wRouteID : wRouteIDList) {
                List<FPCRoutePart> wRPList = FMCServiceImpl.getInstance()
                        .FPC_QueryRoutePartListByRouteID(wLoginUser, wRouteID).List(FPCRoutePart.class);
                wRoutePartList.addAll(wRPList);
            }

            wASList.removeIf(p -> wRoutePartList.stream().noneMatch(q -> q.PartID == p.StationID));
            // ⑤遍历排序好的工位数据，创建行数据
            int wNum = 1;
            for (LFSWorkAreaStation wAS : wASList) {
                List<String> wValueList = new ArrayList<>();
                // ①添加序号
                wValueList.add(String.valueOf(wNum));
                // ②添加工位名称
                wValueList.add(APSConstans.GetFPCPartName(wAS.StationID));
                wResult.add(wValueList);
                for (int wShiftID : wShiftIDList) {
                    // ③根据工位和ShiftID获取车辆名称
                    String wCars = this.GetCars(wShiftID, wAS, wTaskPartList);
                    if (StringUtils.isNotEmpty(wSuffix)) {
                        wCars = wCars.replace(wSuffix, "");
                    }
                    // ④添加车辆
                    wValueList.add(wCars);
                }
                wNum++;
            }
        } catch (Exception e) {
            logger.error(e.toString());
        }
        return wResult;
    }

    /**
     * 根据工位和ShiftID获取车辆名称
     */
    private String GetCars(int wShiftID, LFSWorkAreaStation wAS, List<APSTaskPart> wTaskPartList) {
        String wResult = "";
        try {
            List<APSTaskPart> wList = wTaskPartList.stream().filter(p -> p.PartID == wAS.StationID)
                    .collect(Collectors.toList());

            if (wList.size() <= 0) {
                return wResult;
            }

            List<String> wCars = new ArrayList<>();
            SimpleDateFormat wSDF = new SimpleDateFormat("yyyyMMdd");

            for (APSTaskPart wAPSTaskPart : wList) {
                Calendar wS = (Calendar) wAPSTaskPart.StartTime.clone();
                Calendar wE = (Calendar) wAPSTaskPart.EndTime.clone();
                int wShiftS = Integer.parseInt(wSDF.format(wS.getTime()));
                int wShiftE = Integer.parseInt(wSDF.format(wE.getTime()));

                if (wShiftE > wShiftS) {
                    wE.add(Calendar.DATE, -1);
                    wShiftE = Integer.parseInt(wSDF.format(wE.getTime()));
                }

                if (wShiftID >= wShiftS && wShiftID <= wShiftE
                        && wCars.stream().noneMatch(p -> p.equals(wAPSTaskPart.PartNo))) {
                    wCars.add(wAPSTaskPart.PartNo);
                }
            }
            if (wCars.size() > 0) {
                wResult = StringUtils.Join(",", wCars);
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
        return wResult;
    }

    /**
     * 根据排程版本获取滚动计划表头
     */
    private List<String> GetHeaderList(APSSchedulingVersion wVersion) {
        List<String> wResult = new ArrayList<>();
        try {
            wResult.add("序号");
            wResult.add("工位");

            SimpleDateFormat wSDF = new SimpleDateFormat("yyyyMMdd");
            SimpleDateFormat wSDF1 = new SimpleDateFormat("MM月dd日");

            Calendar wS = (Calendar) wVersion.StartTime.clone();
            Calendar wE = (Calendar) wVersion.EndTime.clone();

            while (Integer.parseInt(wSDF.format(wS.getTime())) <= Integer.parseInt(wSDF.format(wE.getTime()))) {
                wResult.add(wSDF1.format(wS.getTime()));
                wS.add(Calendar.DATE, 1);
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
        return wResult;
    }

    /**
     * 根据排程时间获取班次集合
     */
    private List<Integer> GetShiftIDs(APSSchedulingVersion wVersion) {
        List<Integer> wResult = new ArrayList<>();
        try {
            SimpleDateFormat wSDF = new SimpleDateFormat("yyyyMMdd");

            Calendar wS = (Calendar) wVersion.StartTime.clone();
            Calendar wE = (Calendar) wVersion.EndTime.clone();

            while (Integer.parseInt(wSDF.format(wS.getTime())) <= Integer.parseInt(wSDF.format(wE.getTime()))) {
                wResult.add(Integer.parseInt(wSDF.format(wS.getTime())));
                wS.add(Calendar.DATE, 1);
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<APSTaskPart>> APS_QueryTaskPartList(BMSEmployee wLoginUser, int wOrderID,
                                                                  Calendar wStartTime, Calendar wEndTime,
                                                                  int wAPSShiftPeriod) {
        ServiceResult<List<APSTaskPart>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            wResult.Result = APSTaskPartDAO.getInstance().SelectList(wLoginUser, -1, wOrderID, -1, -1, -1, 1,
                    wAPSShiftPeriod, null, -1, wStartTime, wEndTime, wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<APSSchedulingVersionBPM> APS_QueryDefaultSchedulingVersionBPM(BMSEmployee wLoginUser,
                                                                                       int wEventID) {
        ServiceResult<APSSchedulingVersionBPM> wResult = new ServiceResult<>();
        wResult.Result = new APSSchedulingVersionBPM();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            int wAPSShiftPeriod = 0;
            switch (BPMEventModule.getEnumType(wEventID)) {
                case SCMonthAudit:
                    wAPSShiftPeriod = APSShiftPeriod.Month.getValue();
                    break;
                case SCWeekAudit:
                    wAPSShiftPeriod = APSShiftPeriod.Week.getValue();
                    break;
                default:
                    break;
            }

            List<APSSchedulingVersionBPM> wList = APSSchedulingVersionBPMDAO.getInstance().SelectList(wLoginUser, -1,
                    "", -1, wLoginUser.ID, "", "", wAPSShiftPeriod, -1,
                    new ArrayList<>(Collections.singletonList(APSTaskStatus.Default.getValue())), null, null, null,
                    wErrorCode);
            if (wList != null && wList.size() > 0) {
                wResult.Result = wList.get(0);
                wResult.Result.CreateTime = Calendar.getInstance();
                wResult.Result.SubmitTime = Calendar.getInstance();
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public synchronized ServiceResult<APSSchedulingVersionBPM> APS_CreateSchedulingVersionBPM(BMSEmployee wLoginUser,
                                                                                              BPMEventModule wEventID) {
        ServiceResult<APSSchedulingVersionBPM> wResult = new ServiceResult<>();
        wResult.Result = new APSSchedulingVersionBPM();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            int wAPSShiftPeriod = 0;
            switch (wEventID) {
                case SCMonthAudit:
                    wAPSShiftPeriod = APSShiftPeriod.Month.getValue();
                    break;
                case SCWeekAudit:
                    wAPSShiftPeriod = APSShiftPeriod.Week.getValue();
                    break;
                default:
                    break;
            }

            wResult.Result.APSShiftPeriod = wAPSShiftPeriod;
            wResult.Result.Code = APSSchedulingVersionBPMDAO.getInstance().GetNewCode(wLoginUser, wErrorCode,
                    APSShiftPeriod.getEnumType(wAPSShiftPeriod));
            wResult.Result.CreateTime = Calendar.getInstance();
            wResult.Result.FlowType = wEventID.getValue();
            wResult.Result.ID = 0;
            wResult.Result.Status = APSTaskStatus.Default.getValue();
            wResult.Result.StatusText = "";
            wResult.Result.SubmitTime = Calendar.getInstance();
            wResult.Result.UpFlowID = wLoginUser.ID;
            wResult.Result.VersionNo = wResult.Result.Code;

            wResult.Result.UpFlowName = wLoginUser.Name;

            wResult.Result = (APSSchedulingVersionBPM) APSSchedulingVersionBPMDAO.getInstance()
                    .BPM_UpdateTask(wLoginUser, wResult.Result, wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;

    }

    @Override
    public synchronized ServiceResult<APSSchedulingVersionBPM> APS_SubmitSchedulingVersionBPM(BMSEmployee wLoginUser,
                                                                                              APSSchedulingVersionBPM wData) {
        ServiceResult<APSSchedulingVersionBPM> wResult = new ServiceResult<>();
        wResult.Result = new APSSchedulingVersionBPM();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            // 提交
            List<APSTaskPart> wList = APSTaskPartDAO.getInstance().SelectListByIDList(wLoginUser, wData.TaskPartIDList,
                    wErrorCode);

            if (wData.Status == 2 && wList.stream().anyMatch(p -> p.Status != 1)) {
                wResult.FaultCode += "提示：请提交未排的数据!";
                return wResult;
            }

            if (wData.Status == 2) {
                for (APSTaskPart wAPSTaskPart : wList) {
                    wAPSTaskPart.Status = APSTaskStatus.ToAudit.getValue();
                    APSTaskPartDAO.getInstance().Update(wLoginUser, wAPSTaskPart, wErrorCode);
                }
            } else if (wData.Status == 22) {
                for (APSTaskPart wAPSTaskPart : wList) {
                    wAPSTaskPart.Status = APSTaskStatus.Saved.getValue();
                    APSTaskPartDAO.getInstance().Update(wLoginUser, wAPSTaskPart, wErrorCode);
                }
            } else if (wData.Status == 1) {
                for (APSTaskPart wAPSTaskPart : wList) {
                    wAPSTaskPart.Status = APSTaskStatus.Saved.getValue();
                    APSTaskPartDAO.getInstance().Update(wLoginUser, wAPSTaskPart, wErrorCode);
                }
            } else if (wData.Status == 5) {
                for (APSTaskPart wAPSTaskPart : wList) {
                    wAPSTaskPart.Status = APSTaskStatus.Audited.getValue();
                    APSTaskPartDAO.getInstance().Update(wLoginUser, wAPSTaskPart, wErrorCode);
                }
            } else if (wData.Status == 20) {
                for (APSTaskPart wAPSTaskPart : wList) {
                    wAPSTaskPart.Status = APSTaskStatus.Issued.getValue();

                    // 根据订单ID和工位ID判断是否是不做的工位
                    boolean wCheckFlag = APSTaskPartDAO.getInstance().CheckIsNotDo(wLoginUser, wAPSTaskPart.OrderID,
                            wAPSTaskPart.PartID, wErrorCode);
                    if (wCheckFlag) {
                        wAPSTaskPart.Active = 2;
                    }

                    APSTaskPartDAO.getInstance().Update(wLoginUser, wAPSTaskPart, wErrorCode);
                }

                APSSchedulingVersion wScheduling = APSSchedulingVersionDAO.getInstance().SelectByVersionNo(wLoginUser,
                        wData.VersionNo, wErrorCode);
                if (wScheduling != null && wScheduling.ID > 0) {
                    wScheduling.Status = APSTaskStatus.Issued.getValue();
                    APSSchedulingVersionDAO.getInstance().Update(wLoginUser, wScheduling, wErrorCode);

                    if (wData.APSShiftPeriod == APSShiftPeriod.Week.getValue()) {
                        wScheduling.APSTaskPartList = APSTaskPartDAO.getInstance().SelectListByIDList(wLoginUser,
                                wScheduling.TaskPartIDList, wErrorCode);

                        String materialManage = Configuration.readConfigString("materialManage", "config/config");

                        // 触发日计划
                        ExecutorService wES = Executors.newFixedThreadPool(1);
                        wES.submit(() -> {
                            APS_TriggerDayPlans(wLoginUser, wScheduling);
                            // 触发物料需求计划
                            if (materialManage.equals("1")) {
                                APS_TriggerMRP(wLoginUser, wData, wScheduling);
                            }
                        });
                        wES.shutdown();
                    }
                }

                // 同步配送单的日期
                ExecutorService wES = Executors.newFixedThreadPool(1);
                wES.submit(() -> MyHelperServiceImpl.getInstance().WMS_SynchronizeExpectTimeByTaskPartList(wLoginUser,
                        wList));
                wES.shutdown();
            } else if (wData.Status == 21) {
                wData.StatusText = "已驳回";
                for (APSTaskPart wAPSTaskPart : wList) {
                    wAPSTaskPart.Status = APSTaskStatus.Saved.getValue();
                    APSTaskPartDAO.getInstance().Update(wLoginUser, wAPSTaskPart, wErrorCode);
                }
            }

            if (wData.Status == 20) {
                wData.StatusText = "已下达";
            }

            wResult.Result = (APSSchedulingVersionBPM) APSSchedulingVersionBPMDAO.getInstance()
                    .BPM_UpdateTask(wLoginUser, wData, wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    /**
     * 触发物料需求计划
     */
    private void APS_TriggerMRP(BMSEmployee wLoginUser, APSSchedulingVersionBPM wAPSSchedulingVersionBPM,
                                APSSchedulingVersion wScheduling) {
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            String wMRPMaterialPlanDays = Configuration.readConfigString("mrpmaterialplandays", "config/config");
            int wPlanDays = StringUtils.parseInt(wMRPMaterialPlanDays);
            String testOrder = Configuration.readConfigString("testOrder", "config/config");
            String wNoPickDemandPartIDs = Configuration.readConfigString("NoPickDemandPartIDs", "config/config");
            List<Integer> wFilterPartIDList = StringUtils.parseIntList(wNoPickDemandPartIDs.split(","));
            // ①遍历工位计划
            Calendar wDate = Calendar.getInstance();
            wDate.set(2022, 3, 28, 0, 0, 0);

            // 读取系统配置，只生成配置的相关工位
            String wOutLLParts = MESSystemConfigDAO.getInstance().SelectValueByKey(wLoginUser,
                    "Out.LL.Parts", wErrorCode);
            List<Integer> wOutLLPartsList = StringUtils.parseIntList(wOutLLParts.split(","));

            for (APSTaskPart wAPSTaskPart : wScheduling.APSTaskPartList) {
                OMSOrder wOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wAPSTaskPart.OrderID, wErrorCode);

                // 拆解工位不生成物料需求计划
                if (wFilterPartIDList.stream().anyMatch(p -> p == wAPSTaskPart.PartID)) {
                    continue;
                }

                // 2022-3-28之前进厂的车不生成配送物料计划
                if (wOrder.RealReceiveDate.compareTo(wDate) < 0) {
                    continue;
                }

                if (!testOrder.equals("0") && !testOrder.contains(String.valueOf(wAPSTaskPart.OrderID))) {
                    continue;
                }
                // ②禁用该订单、该工位的物料需求计划(必换件、委外必修件)
                int wNumber = MRPMaterialPlanDAO.getInstance().GetMaterialPlanNumber(wLoginUser, wAPSTaskPart.OrderID,
                        wAPSTaskPart.PartID,
                        wErrorCode);
                if (wNumber > 0) {
                    continue;
                }
                // ③查询台车bom(必换件、委外必修件)
                List<APSBOMItem> wList = APSBOMItemDAO.getInstance().APS_QueryBOMItemList(wLoginUser,
                        wAPSTaskPart.OrderID, "", "", -1, -1, -1, wAPSTaskPart.PartID, -1, -1, "", -1, -1, -1, null, -1,
                        -1, -1, wErrorCode);
                //剔除带删除标记的子项
                wList.removeIf(p -> StringUtils.isNotEmpty(p.DeleteID));

                if (wList == null || wList.size() <= 0) {
                    continue;
                }
                // ④创建物料需求计划
                List<MRPMaterialPlan> wPlanList = new ArrayList<>();

                // 获取物料类型字典：主料或反冲料
                List<Integer> wMaterialIDList = wList.stream().map(p -> p.MaterialID).distinct()
                        .collect(Collectors.toList());
                Map<Integer, Integer> wMaterialTypeMap = MRPMaterialPlanDAO.getInstance().GetMaterialTypeMap(wLoginUser,
                        wMaterialIDList, wErrorCode);

                boolean wOutsourcingPlan = Configuration.readConfigString("OutsourcingPlan", "config/config").equals(
                        "1");
//                boolean wIsSendRecoilMaterial = Configuration.readConfigString("IsSendRecoilMaterial", "config/config")
//                        .equals("1");

                // 查询工序计划，计算最小日期，防止部件计划日期错误
                List<APSTaskStep> apsTaskSteps = APSTaskStepDAO.getInstance().SelectList(wLoginUser, -1, -1, -1,
                        wAPSTaskPart.ID,
                        -1, -1, -1, -1, -1, 1, null, null, null,
                        null, wErrorCode);
                if (apsTaskSteps != null && apsTaskSteps.size() > 0) {
                    APSTaskStep apsTaskStep = apsTaskSteps.stream()
                            .min(Comparator.comparing(APSTaskStep::getPlanStartTime)).get();
                    if (apsTaskStep.PlanStartTime.compareTo(wAPSTaskPart.StartTime) > 0) {
                        wAPSTaskPart.StartTime = apsTaskStep.PlanStartTime;
                    }
                }

                for (APSBOMItem apsbomItem : wList) {
                    // 若没排此工序，不能生成此工序的物料需求
                    if (apsTaskSteps != null && apsTaskSteps.size() > 0
                            && apsTaskSteps.stream().noneMatch(p -> p.StepID == apsbomItem.PartPointID)) {
                        continue;
                    }

                    int wMaterialType = 1;
                    if (wMaterialTypeMap.containsKey(apsbomItem.MaterialID)) {
                        wMaterialType = wMaterialTypeMap.get(apsbomItem.MaterialID);
                    }

                    // 委外和反冲不生成需求计划
                    if (!wOutsourcingPlan && apsbomItem.ReplaceType != 1) {
                        continue;
                    }
//                    if (!wIsSendRecoilMaterial && wMaterialType != 1) {
//                        continue;
//                    }

                    MRPMaterialPlan wMRPMaterialPlan = new MRPMaterialPlan(0, apsbomItem.ProductID, apsbomItem.LineID,
                            apsbomItem.CustomerID, apsbomItem.OrderID, apsbomItem.PartNo, apsbomItem.PartID,
                            apsbomItem.PartPointID, apsbomItem.MaterialID, apsbomItem.MaterialName,
                            apsbomItem.MaterialNo, wMaterialType, apsbomItem.Number, wAPSTaskPart.StartTime,
                            wAPSSchedulingVersionBPM.Code, 1, Calendar.getInstance(), wLoginUser.ID,
                            apsbomItem.ReplaceType, apsbomItem.OutsourceType, 1, apsbomItem.WBSNo,
                            apsbomItem.AssessmentType, apsbomItem.OrderNum, apsbomItem.OriginalType);
                    MRPMaterialPlanDAO.getInstance().Update(wLoginUser, wMRPMaterialPlan, wErrorCode);
                    wPlanList.add(wMRPMaterialPlan);
                }

                Calendar wSTime = (Calendar) wAPSTaskPart.StartTime.clone();
                wSTime.add(Calendar.DATE, -wPlanDays);
                wSTime.set(wSTime.get(Calendar.YEAR), wSTime.get(Calendar.MONTH), wSTime.get(Calendar.DATE), 0, 0, 0);

                Calendar wTTime = Calendar.getInstance();
                wTTime.set(wTTime.get(Calendar.YEAR), wTTime.get(Calendar.MONTH), wTTime.get(Calendar.DATE), 0, 0, 0);

                if (wTTime.compareTo(wSTime) >= 0 && wPlanList.size() > 0) {
                    // ⑤触发必换件物料配送单
                    TriggerMaterialDistributionSheet(BaseDAO.SysAdmin, wPlanList,
                            MRPMaterialPlanStatus.SystemSubmit.getValue());
                    if (wOutsourcingPlan) {
                        // 包含工位ID的才进行委外物料需求生成
                        if (wOutLLPartsList.stream().anyMatch(p -> p.intValue() == wAPSTaskPart.PartID)
                                || wOutLLPartsList.size() == 0) {
                            // 触发委外必修件物料配送单
                            TriggerMaterialDistributionSheet_Out(BaseDAO.SysAdmin, wPlanList,
                                    MRPMaterialPlanStatus.SystemSubmit.getValue());
                        }
                    }
                }
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    /**
     * 触发物料配送单（必换件）
     *
     * @param wLoginUser             登录信息
     * @param wList                  必换件、委外必修件台车bom
     * @param wMRPMaterialPlanStatus 工位计划
     */
    public void TriggerMaterialDistributionSheet(BMSEmployee wLoginUser, List<MRPMaterialPlan> wList,
                                                 int wMRPMaterialPlanStatus) {
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            OMSOrder wOMSOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wList.get(0).OrderID, wErrorCode);

            wList = wList.stream().filter(p -> p.ReplaceType == 1).collect(Collectors.toList());

            // 判断需求是否已提
            List<WMSPickDemand> wExsitList = WMSPickDemandDAO.getInstance().SelectList(wLoginUser, -1,
                    String.valueOf(WMSOrderType.LineOrder.getValue()), "", wList.get(0).ProductID, wList.get(0).LineID,
                    wList.get(0).CustomerID, String.valueOf(wList.get(0).OrderID), wList.get(0).PartID, -1, null,
                    null, null,
                    wErrorCode);
            wExsitList.removeIf(p -> p.SourceType != WMSPickDemandSourceType.Plan.getValue());
            if (wExsitList.size() > 0) {
                // 取消计划，或不指定
                return;
            }

            //反冲料剔除逻辑（生产计划）
            boolean wIsSendRecoilMaterial = Configuration.readConfigString("IsSendRecoilMaterial", "config/config")
                    .equals("1");
            if (!wIsSendRecoilMaterial) {
                wList.removeIf(p -> p.MaterialType == MSSMaterialType.RecoilMaterial.getValue());
                if (wList.size() <= 0) {
                    return;
                }
            }

            //客供料剔除逻辑
            String customerMaterial = MESSystemConfigDAO.getInstance().SelectValueByKey(wLoginUser, "wms.split.customer.demand", wErrorCode);
            if (customerMaterial.equals("1")) {
                //获取客供料
                List<MRPMaterialPlan> customerMaterialList = wList.stream().filter(p -> p.CustomerMaterial == 1).collect(Collectors.toList());
                TriggerMaterialDistributionSheet_Customer(wLoginUser, customerMaterialList, wMRPMaterialPlanStatus);

                //剔除客供料
                wList.removeIf(p -> p.CustomerMaterial == 1);
                if (wList.size() <= 0) {
                    return;
                }
            }

            // ③创建领料需求单
            Calendar wBaseTime = Calendar.getInstance();
            wBaseTime.set(2000, 0, 1, 0, 0, 0);

            String wCode = WMSPickDemandDAO.getInstance().GetNewCode(wLoginUser, wErrorCode);
            Calendar wTime = wList.get(0).DemandDate;

            Calendar expectTime1 = Calendar.getInstance();
            expectTime1.set(wTime.get(Calendar.YEAR), wTime.get(Calendar.MONTH), wTime.get(Calendar.DATE), 0, 0, 0);

            Calendar expectTime2 = Calendar.getInstance();
            expectTime2.set(wTime.get(Calendar.YEAR), wTime.get(Calendar.MONTH), wTime.get(Calendar.DATE), 12, 0, 0);

            String monitorNo = "";
            String monitor = "";
            BMSEmployee wUser = WMSPickDemandDAO.getInstance().GetMonitorByPart(wLoginUser, wList.get(0).PartID,
                    wErrorCode);
            if (StringUtils.isNotEmpty(wUser.LoginID)) {
                monitorNo = wUser.LoginID;
                monitor = wUser.Name;
            }

            WMSPickDemand wWMSPickDemand = new WMSPickDemand(0, "1900",
                    String.valueOf(WMSOrderType.LineOrder.getValue()), wCode, expectTime1, expectTime2, monitorNo,
                    monitor, wList.get(0).ProductID, APSConstans.GetFPCProductNo(wList.get(0).ProductID),
                    wList.get(0).LineID, APSConstans.GetFMCLineName(wList.get(0).LineID), wList.get(0).CustomerID,
                    APSConstans.GetCRMCustomer(wList.get(0).CustomerID).CustomerName,
                    APSConstans.GetCRMCustomer(wList.get(0).CustomerID).CustomerCode, wList.get(0).OrderID,
                    wList.get(0).PartNo, wList.get(0).PartID, APSConstans.GetFPCPartName(wList.get(0).PartID),
                    APSConstans.GetFPCPart(wList.get(0).PartID).Code, "", "", wBaseTime, "", "", wBaseTime, 1,
                    wLoginUser.ID, wLoginUser.Name, Calendar.getInstance(), wList.get(0).WBSNo, wBaseTime);
            wWMSPickDemand.SourceType = WMSPickDemandSourceType.Plan.getValue();
            int wDemandID = WMSPickDemandDAO.getInstance().Update(wLoginUser, wWMSPickDemand, wErrorCode);
            if (wDemandID <= 0) {
                return;
            }
            // ④创建领料需求单明细
            int wIndex = 1;

            List<Integer> wMaterialIDList = wList.stream()
                    .filter(p -> p.MaterialType == MSSMaterialType.RecoilMaterial.getValue()).map(p -> p.MaterialID)
                    .distinct().collect(Collectors.toList());
            // 获取物料最小包装字典
            Map<Integer, Double> wMaterialPackMap = MRPMaterialPlanDAO.getInstance().GetMaterialPackMap(wLoginUser,
                    wMaterialIDList, wErrorCode);

            // 获取配套属性
            Map<Integer, String> wMaterialMatchMap = MRPMaterialPlanDAO.getInstance()
                    .GetMaterialMatchMap(BaseDAO.SysAdmin, wMaterialIDList, wErrorCode);

            for (MRPMaterialPlan wMRPMaterialPlan : wList) {
                double wFQTY = wMRPMaterialPlan.FQTY;
                // 根据最小包装计算需求
                if (wMaterialPackMap.containsKey(wMRPMaterialPlan.MaterialID)) {
                    double wMinPack = wMaterialPackMap.get(wMRPMaterialPlan.MaterialID);
                    if (wMinPack > 0) {
                        int wAreaID = APSUtils.getInstance().GetAreaID(wMRPMaterialPlan.PartID);
                        wFQTY = WMSServiceImpl.getInstance().WMS_GetRealLLNumber(wLoginUser, wMinPack,
                                wMRPMaterialPlan.MaterialID, wMRPMaterialPlan.FQTY, wAreaID, wErrorCode).Result;
                    }
                }

                // 获取配套属性
                String wGroup = "";
                if (wMaterialMatchMap.containsKey(wMRPMaterialPlan.MaterialID)) {
                    wGroup = wMaterialMatchMap.get(wMRPMaterialPlan.MaterialID);
                }

                WMSPickDemandItem wWMSPickDemandItem = new WMSPickDemandItem(0, wDemandID,
                        wMRPMaterialPlan.MaterialID, wMRPMaterialPlan.MaterialNo, wMRPMaterialPlan.MaterialName,
                        wFQTY, wOMSOrder.OrderNo, wMRPMaterialPlan.StepID,
                        APSConstans.GetFPCPartPoint(wMRPMaterialPlan.StepID).Code.replace("PS-", ""),
                        APSConstans.GetFPCPartPointName(wMRPMaterialPlan.StepID), String.valueOf(wIndex), wGroup,
                        wMRPMaterialPlan.ReplaceType,
                        SFCReplaceType.getEnumType(wMRPMaterialPlan.ReplaceType).getLable(),
                        wMRPMaterialPlan.OutSourceType,
                        SFCOutSourceType.getEnumType(wMRPMaterialPlan.OutSourceType).getLable(),
                        wMRPMaterialPlan.AssessmentType, "", wBaseTime, wWMSPickDemand.PartID,
                        wMRPMaterialPlan.MaterialType, wMRPMaterialPlan.FQTY, wMRPMaterialPlan.BOMItemNum);

                wWMSPickDemandItem.IsOriDis = wMRPMaterialPlan.OriginalType == 1 ? "是" : "否";

                int wItemID = WMSPickDemandItemDAO.getInstance().Update(wLoginUser, wWMSPickDemandItem, wErrorCode);
                if (wItemID > 0 && wWMSPickDemandItem.FQTY < wMRPMaterialPlan.FQTY) {
                    WMSServiceImpl.getInstance().WMS_RecoilMaterialUse(wLoginUser, wItemID);
                }
                wIndex++;
            }
            // ⑤关联物料需求计划
            int wOrderID = wList.get(0).OrderID;
            int wPartID = wList.get(0).PartID;
            List<MRPMaterialPlan> wPList = wList.stream()
                    .filter(p -> p.OrderID == wOrderID && p.PartID == wPartID && p.Active == 1)
                    .collect(Collectors.toList());
            for (MRPMaterialPlan wMRPMaterialPlan : wPList) {
                wMRPMaterialPlan.Status = wMRPMaterialPlanStatus;
                wMRPMaterialPlan.EditID = wLoginUser.ID;
                wMRPMaterialPlan.EditTime = Calendar.getInstance();
                wMRPMaterialPlan.WMSPickDemandID = wDemandID;
                MRPMaterialPlanDAO.getInstance().Update(wLoginUser, wMRPMaterialPlan, wErrorCode);
            }

            // 推送物料需求计划
            WMSServiceImpl.getInstance().WMS_ManualPush(wLoginUser, wDemandID);
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    /**
     * 触发物料配送单（必换件_客供料）
     *
     * @param wLoginUser             登录信息
     * @param wList                  必换件、委外必修件台车bom
     * @param wMRPMaterialPlanStatus 工位计划
     */
    public void TriggerMaterialDistributionSheet_Customer(BMSEmployee wLoginUser, List<MRPMaterialPlan> wList,
                                                          int wMRPMaterialPlanStatus) {
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            OMSOrder wOMSOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wList.get(0).OrderID, wErrorCode);

            // ③创建领料需求单
            Calendar wBaseTime = Calendar.getInstance();
            wBaseTime.set(2000, 0, 1, 0, 0, 0);

            String wCode = WMSPickDemandDAO.getInstance().GetNewCode(wLoginUser, wErrorCode);
            Calendar wTime = wList.get(0).DemandDate;

            Calendar expectTime1 = Calendar.getInstance();
            expectTime1.set(wTime.get(Calendar.YEAR), wTime.get(Calendar.MONTH), wTime.get(Calendar.DATE), 0, 0, 0);

            Calendar expectTime2 = Calendar.getInstance();
            expectTime2.set(wTime.get(Calendar.YEAR), wTime.get(Calendar.MONTH), wTime.get(Calendar.DATE), 12, 0, 0);

            String monitorNo = "";
            String monitor = "";
            BMSEmployee wUser = WMSPickDemandDAO.getInstance().GetMonitorByPart(wLoginUser, wList.get(0).PartID,
                    wErrorCode);
            if (StringUtils.isNotEmpty(wUser.LoginID)) {
                monitorNo = wUser.LoginID;
                monitor = wUser.Name;
            }

            WMSPickDemand wWMSPickDemand = new WMSPickDemand(0, "1900",
                    String.valueOf(WMSOrderType.CustomerLL.getValue()), wCode, expectTime1, expectTime2, monitorNo,
                    monitor, wList.get(0).ProductID, APSConstans.GetFPCProductNo(wList.get(0).ProductID),
                    wList.get(0).LineID, APSConstans.GetFMCLineName(wList.get(0).LineID), wList.get(0).CustomerID,
                    APSConstans.GetCRMCustomer(wList.get(0).CustomerID).CustomerName,
                    APSConstans.GetCRMCustomer(wList.get(0).CustomerID).CustomerCode, wList.get(0).OrderID,
                    wList.get(0).PartNo, wList.get(0).PartID, APSConstans.GetFPCPartName(wList.get(0).PartID),
                    APSConstans.GetFPCPart(wList.get(0).PartID).Code, "", "", wBaseTime, "", "", wBaseTime, 1,
                    wLoginUser.ID, wLoginUser.Name, Calendar.getInstance(), wList.get(0).WBSNo, wBaseTime);
            wWMSPickDemand.SourceType = WMSPickDemandSourceType.Plan.getValue();
            int wDemandID = WMSPickDemandDAO.getInstance().Update(wLoginUser, wWMSPickDemand, wErrorCode);
            if (wDemandID <= 0) {
                return;
            }
            // ④创建领料需求单明细
            int wIndex = 1;
            for (MRPMaterialPlan wMRPMaterialPlan : wList) {
                double wFQTY = wMRPMaterialPlan.FQTY;
                WMSPickDemandItem wWMSPickDemandItem = new WMSPickDemandItem(0, wDemandID,
                        wMRPMaterialPlan.MaterialID, wMRPMaterialPlan.MaterialNo, wMRPMaterialPlan.MaterialName,
                        wFQTY, wOMSOrder.OrderNo, wMRPMaterialPlan.StepID,
                        APSConstans.GetFPCPartPoint(wMRPMaterialPlan.StepID).Code.replace("PS-", ""),
                        APSConstans.GetFPCPartPointName(wMRPMaterialPlan.StepID), String.valueOf(wIndex), "",
                        wMRPMaterialPlan.ReplaceType,
                        SFCReplaceType.getEnumType(wMRPMaterialPlan.ReplaceType).getLable(),
                        wMRPMaterialPlan.OutSourceType,
                        SFCOutSourceType.getEnumType(wMRPMaterialPlan.OutSourceType).getLable(),
                        wMRPMaterialPlan.AssessmentType, "", wBaseTime, wWMSPickDemand.PartID,
                        wMRPMaterialPlan.MaterialType, wMRPMaterialPlan.FQTY, wMRPMaterialPlan.BOMItemNum);

                wWMSPickDemandItem.IsOriDis = wMRPMaterialPlan.OriginalType == 1 ? "是" : "否";
                WMSPickDemandItemDAO.getInstance().Update(wLoginUser, wWMSPickDemandItem, wErrorCode);
                wIndex++;
            }
            // ⑤关联物料需求计划
            int wOrderID = wList.get(0).OrderID;
            int wPartID = wList.get(0).PartID;
            List<MRPMaterialPlan> wPList = wList.stream()
                    .filter(p -> p.OrderID == wOrderID && p.PartID == wPartID && p.Active == 1)
                    .collect(Collectors.toList());
            for (MRPMaterialPlan wMRPMaterialPlan : wPList) {
                wMRPMaterialPlan.Status = wMRPMaterialPlanStatus;
                wMRPMaterialPlan.EditID = wLoginUser.ID;
                wMRPMaterialPlan.EditTime = Calendar.getInstance();
                wMRPMaterialPlan.WMSPickDemandID = wDemandID;
                MRPMaterialPlanDAO.getInstance().Update(wLoginUser, wMRPMaterialPlan, wErrorCode);
            }

            // 推送物料需求计划
            WMSServiceImpl.getInstance().WMS_ManualPush(wLoginUser, wDemandID);
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    /**
     * 触发物料配送单
     *
     * @param wLoginUser             登录信息
     * @param wList                  必换件、委外必修件台车bom
     * @param wMRPMaterialPlanStatus 工位计划
     */
    @Override
    public void TriggerMaterialDistributionSheetNoCheck(BMSEmployee wLoginUser, List<MRPMaterialPlan> wList,
                                                        int wMRPMaterialPlanStatus) {
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            OMSOrder wOMSOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wList.get(0).OrderID, wErrorCode);

            wList = wList.stream().filter(p -> p.ReplaceType == 1).collect(Collectors.toList());

            // ③创建领料需求单
            Calendar wBaseTime = Calendar.getInstance();
            wBaseTime.set(2000, 0, 1, 0, 0, 0);

            String wCode = WMSPickDemandDAO.getInstance().GetNewCode(wLoginUser, wErrorCode);
            Calendar wTime = wList.get(0).DemandDate;

            Calendar expectTime1 = Calendar.getInstance();
            expectTime1.set(wTime.get(Calendar.YEAR), wTime.get(Calendar.MONTH), wTime.get(Calendar.DATE), 0, 0, 0);

            Calendar expectTime2 = Calendar.getInstance();
            expectTime2.set(wTime.get(Calendar.YEAR), wTime.get(Calendar.MONTH), wTime.get(Calendar.DATE), 12, 0, 0);

            String monitorNo = "";
            String monitor = "";
            BMSEmployee wUser = WMSPickDemandDAO.getInstance().GetMonitorByPart(wLoginUser, wList.get(0).PartID,
                    wErrorCode);
            if (StringUtils.isNotEmpty(wUser.LoginID)) {
                monitorNo = wUser.LoginID;
                monitor = wUser.Name;
            }

            WMSPickDemand wWMSPickDemand = new WMSPickDemand(0, "1900",
                    String.valueOf(WMSOrderType.LineOrder.getValue()), wCode, expectTime1, expectTime2, monitorNo,
                    monitor, wList.get(0).ProductID, APSConstans.GetFPCProductNo(wList.get(0).ProductID),
                    wList.get(0).LineID, APSConstans.GetFMCLineName(wList.get(0).LineID), wList.get(0).CustomerID,
                    APSConstans.GetCRMCustomer(wList.get(0).CustomerID).CustomerName,
                    APSConstans.GetCRMCustomer(wList.get(0).CustomerID).CustomerCode, wList.get(0).OrderID,
                    wList.get(0).PartNo, wList.get(0).PartID, APSConstans.GetFPCPartName(wList.get(0).PartID),
                    APSConstans.GetFPCPart(wList.get(0).PartID).Code, "", "", wBaseTime, "", "", wBaseTime, 1,
                    wLoginUser.ID, wLoginUser.Name, Calendar.getInstance(), wList.get(0).WBSNo, wBaseTime);
            wWMSPickDemand.SourceType = WMSPickDemandSourceType.Plan.getValue();
            int wDemandID = WMSPickDemandDAO.getInstance().Update(wLoginUser, wWMSPickDemand, wErrorCode);
            if (wDemandID <= 0) {
                return;
            }
            // ④创建领料需求单明细
            int wIndex = 1;

            List<Integer> wMaterialIDList = wList.stream()
                    .filter(p -> p.MaterialType == MSSMaterialType.RecoilMaterial.getValue()).map(p -> p.MaterialID)
                    .distinct().collect(Collectors.toList());
            // 获取物料最小包装字典
            Map<Integer, Double> wMaterialPackMap = MRPMaterialPlanDAO.getInstance().GetMaterialPackMap(wLoginUser,
                    wMaterialIDList, wErrorCode);

            // 获取配套属性
            Map<Integer, String> wMaterialMatchMap = MRPMaterialPlanDAO.getInstance()
                    .GetMaterialMatchMap(BaseDAO.SysAdmin, wMaterialIDList, wErrorCode);

            for (MRPMaterialPlan wMRPMaterialPlan : wList) {
                double wFQTY = wMRPMaterialPlan.FQTY;
                // 根据最小包装计算需求
                if (wMaterialPackMap.containsKey(wMRPMaterialPlan.MaterialID)) {
                    double wMinPack = wMaterialPackMap.get(wMRPMaterialPlan.MaterialID);
                    if (wMinPack > 0) {
                        int wAreaID = APSUtils.getInstance().GetAreaID(wMRPMaterialPlan.PartID);
                        wFQTY = WMSServiceImpl.getInstance().WMS_GetRealLLNumber(wLoginUser, wMinPack,
                                wMRPMaterialPlan.MaterialID, wMRPMaterialPlan.FQTY, wAreaID, wErrorCode).Result;
                    }
                }

                // 获取配套属性
                String wGroup = "";
                if (wMaterialMatchMap.containsKey(wMRPMaterialPlan.MaterialID)) {
                    wGroup = wMaterialMatchMap.get(wMRPMaterialPlan.MaterialID);
                }

                WMSPickDemandItem wWMSPickDemandItem = new WMSPickDemandItem(0, wDemandID,
                        wMRPMaterialPlan.MaterialID, wMRPMaterialPlan.MaterialNo, wMRPMaterialPlan.MaterialName,
                        wFQTY, wOMSOrder.OrderNo, wMRPMaterialPlan.StepID,
                        APSConstans.GetFPCPartPoint(wMRPMaterialPlan.StepID).Code.replace("PS-", ""),
                        APSConstans.GetFPCPartPointName(wMRPMaterialPlan.StepID), String.valueOf(wIndex), wGroup,
                        wMRPMaterialPlan.ReplaceType,
                        SFCReplaceType.getEnumType(wMRPMaterialPlan.ReplaceType).getLable(),
                        wMRPMaterialPlan.OutSourceType,
                        SFCOutSourceType.getEnumType(wMRPMaterialPlan.OutSourceType).getLable(),
                        wMRPMaterialPlan.AssessmentType, "", wBaseTime, wWMSPickDemand.PartID,
                        wMRPMaterialPlan.MaterialType, wMRPMaterialPlan.FQTY, wMRPMaterialPlan.BOMItemNum);

                wWMSPickDemandItem.IsOriDis = wMRPMaterialPlan.OriginalType == 1 ? "是" : "否";

                int wItemID = WMSPickDemandItemDAO.getInstance().Update(wLoginUser, wWMSPickDemandItem, wErrorCode);
                if (wItemID > 0 && wWMSPickDemandItem.FQTY < wMRPMaterialPlan.FQTY) {
                    WMSServiceImpl.getInstance().WMS_RecoilMaterialUse(wLoginUser, wItemID);
                }
                wIndex++;
            }
            // ⑤关联物料需求计划
            int wOrderID = wList.get(0).OrderID;
            int wPartID = wList.get(0).PartID;
            List<MRPMaterialPlan> wPList = wList.stream()
                    .filter(p -> p.OrderID == wOrderID && p.PartID == wPartID && p.Active == 1)
                    .collect(Collectors.toList());
            for (MRPMaterialPlan wMRPMaterialPlan : wPList) {
                wMRPMaterialPlan.Status = wMRPMaterialPlanStatus;
                wMRPMaterialPlan.EditID = wLoginUser.ID;
                wMRPMaterialPlan.EditTime = Calendar.getInstance();
                wMRPMaterialPlan.WMSPickDemandID = wDemandID;
                MRPMaterialPlanDAO.getInstance().Update(wLoginUser, wMRPMaterialPlan, wErrorCode);
            }

            // 推送物料需求计划
            WMSServiceImpl.getInstance().WMS_ManualPush(wLoginUser, wDemandID);
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    /**
     * 触发委外物料配送单（计划_委外必修）
     *
     * @param wLoginUser             登录信息
     * @param wList                  必换件、委外必修件台车bom
     * @param wMRPMaterialPlanStatus 工位计划
     */
    private void TriggerMaterialDistributionSheet_Out(BMSEmployee wLoginUser, List<MRPMaterialPlan> wList,
                                                      int wMRPMaterialPlanStatus) {
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wList = wList.stream().filter(p -> p.OutSourceType == 1).collect(Collectors.toList());
            OMSOrder wOMSOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wList.get(0).OrderID, wErrorCode);

//            // 查询预检、拆解工步中定义的多选一物料清单
//            List<Integer> wMultiMaterialIDList = QMSServiceImpl.getInstance().IPT_QueryMultiMaterialID(wLoginUser,
//                    wOMSOrder.RouteID, wOMSOrder.LineID, wOMSOrder.ProductID).List(Integer.class);
//            // 排除多选一物料，后续生成这部分物料的委外领料单
//            if (wMultiMaterialIDList != null && wMultiMaterialIDList.size() > 0) {
//                wList.removeIf(p -> wMultiMaterialIDList.stream().anyMatch(q -> q == p.MaterialID));
//            }
            // 判断需求是否已提
            List<WMSPickDemand> wExsitList = WMSPickDemandDAO.getInstance().SelectList(wLoginUser, -1,
                    String.valueOf(WMSOrderType.OutLL.getValue()), "", wList.get(0).ProductID, wList.get(0).LineID,
                    wList.get(0).CustomerID, String.valueOf(wList.get(0).OrderID), wList.get(0).PartID, -1, null,
                    null, null,
                    wErrorCode);
            wExsitList.removeIf(p -> p.SourceType != WMSPickDemandSourceType.Plan_Out.getValue());
            if (wExsitList.size() > 0) {
                // 取消计划，或不指定
                return;
            }

            //反冲料剔除逻辑（生产计划委外）
            boolean wIsSendRecoilMaterial = Configuration.readConfigString("IsSendRecoilMaterial", "config/config")
                    .equals("1");
            if (!wIsSendRecoilMaterial) {
                wList.removeIf(p -> p.MaterialType == MSSMaterialType.RecoilMaterial.getValue());
                if (wList.size() <= 0) {
                    return;
                }
            }

            //客供料剔除逻辑
            String customerMaterial = MESSystemConfigDAO.getInstance().SelectValueByKey(wLoginUser, "wms.split.customer.demand", wErrorCode);
            if (customerMaterial.equals("1")) {
                //获取客供料
                List<MRPMaterialPlan> customerMaterialList = wList.stream().filter(p -> p.CustomerMaterial == 1).collect(Collectors.toList());
                TriggerMaterialDistributionSheet_Customer(wLoginUser, customerMaterialList, wMRPMaterialPlanStatus);

                //剔除客供料
                wList.removeIf(p -> p.CustomerMaterial == 1);
                if (wList.size() <= 0) {
                    return;
                }
            }

            // ③创建领料需求单
            Calendar wBaseTime = Calendar.getInstance();
            wBaseTime.set(2000, 0, 1, 0, 0, 0);

            String wCode = WMSPickDemandDAO.getInstance().GetNewCode(wLoginUser, wErrorCode);
            Calendar wTime = wList.get(0).DemandDate;

            Calendar expectTime1 = Calendar.getInstance();
            expectTime1.set(wTime.get(Calendar.YEAR), wTime.get(Calendar.MONTH), wTime.get(Calendar.DATE), 0, 0, 0);

            Calendar expectTime2 = Calendar.getInstance();
            expectTime2.set(wTime.get(Calendar.YEAR), wTime.get(Calendar.MONTH), wTime.get(Calendar.DATE), 12, 0, 0);

            String monitorNo = "";
            String monitor = "";
            BMSEmployee wUser = WMSPickDemandDAO.getInstance().GetMonitorByPart(wLoginUser, wList.get(0).PartID,
                    wErrorCode);
            if (StringUtils.isNotEmpty(wUser.LoginID)) {
                monitorNo = wUser.LoginID;
                monitor = wUser.Name;
            }

            WMSPickDemand wWMSPickDemand = new WMSPickDemand(0, "1900",
                    String.valueOf(WMSOrderType.OutLL.getValue()), wCode, expectTime1, expectTime2, monitorNo,
                    monitor, wList.get(0).ProductID, APSConstans.GetFPCProductNo(wList.get(0).ProductID),
                    wList.get(0).LineID, APSConstans.GetFMCLineName(wList.get(0).LineID), wList.get(0).CustomerID,
                    APSConstans.GetCRMCustomer(wList.get(0).CustomerID).CustomerName,
                    APSConstans.GetCRMCustomer(wList.get(0).CustomerID).CustomerCode, wList.get(0).OrderID,
                    wList.get(0).PartNo, wList.get(0).PartID, APSConstans.GetFPCPartName(wList.get(0).PartID),
                    APSConstans.GetFPCPart(wList.get(0).PartID).Code, "", "", wBaseTime, "", "", wBaseTime, 1,
                    wLoginUser.ID, wLoginUser.Name, Calendar.getInstance(), wList.get(0).WBSNo, wBaseTime);
            wWMSPickDemand.SourceType = WMSPickDemandSourceType.Plan_Out.getValue();
            int wDemandID = WMSPickDemandDAO.getInstance().Update(wLoginUser, wWMSPickDemand, wErrorCode);
            if (wDemandID <= 0) {
                return;
            }
            // ④创建领料需求单明细
            int wIndex = 1;

            List<Integer> wMaterialIDList = wList.stream()
                    .filter(p -> p.MaterialType == MSSMaterialType.RecoilMaterial.getValue()).map(p -> p.MaterialID)
                    .distinct().collect(Collectors.toList());
            // 获取物料最小包装字典
            Map<Integer, Double> wMaterialPackMap = MRPMaterialPlanDAO.getInstance().GetMaterialPackMap(wLoginUser,
                    wMaterialIDList, wErrorCode);

            // 获取配套属性
            Map<Integer, String> wMaterialMatchMap = MRPMaterialPlanDAO.getInstance()
                    .GetMaterialMatchMap(BaseDAO.SysAdmin, wMaterialIDList, wErrorCode);

            for (MRPMaterialPlan wMRPMaterialPlan : wList) {
                double wFQTY = wMRPMaterialPlan.FQTY;
                // 根据最小包装计算需求
                if (wMaterialPackMap.containsKey(wMRPMaterialPlan.MaterialID)) {
                    double wMinPack = wMaterialPackMap.get(wMRPMaterialPlan.MaterialID);
                    if (wMinPack > 0) {
                        int wAreaID = APSUtils.getInstance().GetAreaID(wMRPMaterialPlan.PartID);
                        wFQTY = WMSServiceImpl.getInstance().WMS_GetRealLLNumber(wLoginUser, wMinPack,
                                wMRPMaterialPlan.MaterialID, wMRPMaterialPlan.FQTY, wAreaID, wErrorCode).Result;
                    }
                }

                // 获取配套属性
                String wGroup = "";
                if (wMaterialMatchMap.containsKey(wMRPMaterialPlan.MaterialID)) {
                    wGroup = wMaterialMatchMap.get(wMRPMaterialPlan.MaterialID);
                }

                WMSPickDemandItem wWMSPickDemandItem = new WMSPickDemandItem(0, wDemandID,
                        wMRPMaterialPlan.MaterialID, wMRPMaterialPlan.MaterialNo, wMRPMaterialPlan.MaterialName,
                        wFQTY, wOMSOrder.OrderNo, wMRPMaterialPlan.StepID,
                        APSConstans.GetFPCPartPoint(wMRPMaterialPlan.StepID).Code.replace("PS-", ""),
                        APSConstans.GetFPCPartPointName(wMRPMaterialPlan.StepID), String.valueOf(wIndex), wGroup,
                        wMRPMaterialPlan.ReplaceType,
                        SFCReplaceType.getEnumType(wMRPMaterialPlan.ReplaceType).getLable(),
                        wMRPMaterialPlan.OutSourceType,
                        SFCOutSourceType.getEnumType(wMRPMaterialPlan.OutSourceType).getLable(),
                        wMRPMaterialPlan.AssessmentType, "", wBaseTime, wWMSPickDemand.PartID,
                        wMRPMaterialPlan.MaterialType, wMRPMaterialPlan.FQTY, wMRPMaterialPlan.BOMItemNum);

                wWMSPickDemandItem.IsOriDis = wMRPMaterialPlan.OriginalType == 1 ? "是" : "否";

                int wItemID = WMSPickDemandItemDAO.getInstance().Update(wLoginUser, wWMSPickDemandItem, wErrorCode);
                if (wItemID > 0 && wWMSPickDemandItem.FQTY == 0) {
                    WMSServiceImpl.getInstance().WMS_RecoilMaterialUse(wLoginUser, wItemID);
                }
                wIndex++;
            }
            // ⑤关联物料需求计划
            int wOrderID = wList.get(0).OrderID;
            int wPartID = wList.get(0).PartID;
            List<MRPMaterialPlan> wPList = wList.stream()
                    .filter(p -> p.OrderID == wOrderID && p.PartID == wPartID && p.Active == 1)
                    .collect(Collectors.toList());
            for (MRPMaterialPlan wMRPMaterialPlan : wPList) {
                wMRPMaterialPlan.Status = wMRPMaterialPlanStatus;
                wMRPMaterialPlan.EditID = wLoginUser.ID;
                wMRPMaterialPlan.EditTime = Calendar.getInstance();
                wMRPMaterialPlan.WMSPickDemandID = wDemandID;
                MRPMaterialPlanDAO.getInstance().Update(wLoginUser, wMRPMaterialPlan, wErrorCode);
            }
            // 推送物料需求计划
            WMSServiceImpl.getInstance().WMS_ManualPush(wLoginUser, wDemandID);
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    /**
     * 触发委外物料配送单（预检拆解_委外必修）
     *
     * @param wLoginUser             登录信息
     * @param wList                  必换件、委外必修件台车bom
     * @param wMRPMaterialPlanStatus 需求计划的状态
     */
    @Override
    public void TriggerMaterialDistributionSheet_PrevAndDisa(BMSEmployee wLoginUser, List<MRPMaterialPlan> wList,
                                                             int wMRPMaterialPlanStatus) {
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wList = wList.stream().filter(p -> p.OutSourceType == 1).collect(Collectors.toList());
            OMSOrder wOMSOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wList.get(0).OrderID, wErrorCode);

            // 判断需求是否已提
            List<WMSPickDemand> wExsitList = WMSPickDemandDAO.getInstance().SelectList(wLoginUser, -1,
                    String.valueOf(WMSOrderType.OutLL.getValue()), "", wList.get(0).ProductID, wList.get(0).LineID,
                    wList.get(0).CustomerID, String.valueOf(wList.get(0).OrderID), wList.get(0).PartID, -1, null,
                    null, null,
                    wErrorCode);
            wExsitList.removeIf(p -> p.SourceType != WMSPickDemandSourceType.Plan_PrevAndDisa.getValue());
            if (wExsitList.size() > 0) {
                // 取消计划，或不指定
                return;
            }
            // ③创建领料需求单
            Calendar wBaseTime = Calendar.getInstance();
            wBaseTime.set(2000, 0, 1, 0, 0, 0);

            String wCode = WMSPickDemandDAO.getInstance().GetNewCode(wLoginUser, wErrorCode);
            Calendar wTime = wList.get(0).DemandDate;

            Calendar expectTime1 = Calendar.getInstance();
            expectTime1.set(wTime.get(Calendar.YEAR), wTime.get(Calendar.MONTH), wTime.get(Calendar.DATE), 0, 0, 0);

            Calendar expectTime2 = Calendar.getInstance();
            expectTime2.set(wTime.get(Calendar.YEAR), wTime.get(Calendar.MONTH), wTime.get(Calendar.DATE), 12, 0, 0);

            String monitorNo = "";
            String monitor = "";
            BMSEmployee wUser = WMSPickDemandDAO.getInstance().GetMonitorByPart(wLoginUser, wList.get(0).PartID,
                    wErrorCode);
            if (StringUtils.isNotEmpty(wUser.LoginID)) {
                monitorNo = wUser.LoginID;
                monitor = wUser.Name;
            }

            WMSPickDemand wWMSPickDemand = new WMSPickDemand(0, "1900",
                    String.valueOf(WMSOrderType.OutLL.getValue()), wCode, expectTime1, expectTime2, monitorNo,
                    monitor, wList.get(0).ProductID, APSConstans.GetFPCProductNo(wList.get(0).ProductID),
                    wList.get(0).LineID, APSConstans.GetFMCLineName(wList.get(0).LineID), wList.get(0).CustomerID,
                    APSConstans.GetCRMCustomer(wList.get(0).CustomerID).CustomerName,
                    APSConstans.GetCRMCustomer(wList.get(0).CustomerID).CustomerCode, wList.get(0).OrderID,
                    wList.get(0).PartNo, wList.get(0).PartID, APSConstans.GetFPCPartName(wList.get(0).PartID),
                    APSConstans.GetFPCPart(wList.get(0).PartID).Code, "", "", wBaseTime, "", "", wBaseTime, 1,
                    wLoginUser.ID, wLoginUser.Name, Calendar.getInstance(), wList.get(0).WBSNo, wBaseTime);
            wWMSPickDemand.SourceType = WMSPickDemandSourceType.Plan_PrevAndDisa.getValue();
            int wDemandID = WMSPickDemandDAO.getInstance().Update(wLoginUser, wWMSPickDemand, wErrorCode);
            if (wDemandID <= 0) {
                return;
            }
            // ④创建领料需求单明细
            int wIndex = 1;

            List<Integer> wMaterialIDList = wList.stream()
                    .filter(p -> p.MaterialType == MSSMaterialType.RecoilMaterial.getValue()).map(p -> p.MaterialID)
                    .distinct().collect(Collectors.toList());
            // 获取物料最小包装字典
            Map<Integer, Double> wMaterialPackMap = MRPMaterialPlanDAO.getInstance().GetMaterialPackMap(wLoginUser,
                    wMaterialIDList, wErrorCode);

            // 获取配套属性
            Map<Integer, String> wMaterialMatchMap = MRPMaterialPlanDAO.getInstance()
                    .GetMaterialMatchMap(BaseDAO.SysAdmin, wMaterialIDList, wErrorCode);

            for (MRPMaterialPlan wMRPMaterialPlan : wList) {
                double wFQTY = wMRPMaterialPlan.FQTY;
                // 根据最小包装计算需求
                if (wMaterialPackMap.containsKey(wMRPMaterialPlan.MaterialID)) {
                    double wMinPack = wMaterialPackMap.get(wMRPMaterialPlan.MaterialID);
                    if (wMinPack > 0) {
                        int wAreaID = APSUtils.getInstance().GetAreaID(wMRPMaterialPlan.PartID);
                        wFQTY = WMSServiceImpl.getInstance().WMS_GetRealLLNumber(wLoginUser, wMinPack,
                                wMRPMaterialPlan.MaterialID, wMRPMaterialPlan.FQTY, wAreaID, wErrorCode).Result;
                    }
                }

                // 获取配套属性
                String wGroup = "";
                if (wMaterialMatchMap.containsKey(wMRPMaterialPlan.MaterialID)) {
                    wGroup = wMaterialMatchMap.get(wMRPMaterialPlan.MaterialID);
                }

                WMSPickDemandItem wWMSPickDemandItem = new WMSPickDemandItem(0, wDemandID,
                        wMRPMaterialPlan.MaterialID, wMRPMaterialPlan.MaterialNo, wMRPMaterialPlan.MaterialName,
                        wFQTY, wOMSOrder.OrderNo, wMRPMaterialPlan.StepID,
                        APSConstans.GetFPCPartPoint(wMRPMaterialPlan.StepID).Code.replace("PS-", ""),
                        APSConstans.GetFPCPartPointName(wMRPMaterialPlan.StepID), String.valueOf(wIndex), wGroup,
                        wMRPMaterialPlan.ReplaceType,
                        SFCReplaceType.getEnumType(wMRPMaterialPlan.ReplaceType).getLable(),
                        wMRPMaterialPlan.OutSourceType,
                        SFCOutSourceType.getEnumType(wMRPMaterialPlan.OutSourceType).getLable(),
                        wMRPMaterialPlan.AssessmentType, "", wBaseTime, wWMSPickDemand.PartID,
                        wMRPMaterialPlan.MaterialType, wMRPMaterialPlan.FQTY, wMRPMaterialPlan.BOMItemNum);

                wWMSPickDemandItem.IsOriDis = wMRPMaterialPlan.OriginalType == 1 ? "是" : "否";

                int wItemID = WMSPickDemandItemDAO.getInstance().Update(wLoginUser, wWMSPickDemandItem, wErrorCode);
                if (wItemID > 0 && wWMSPickDemandItem.FQTY == 0) {
                    WMSServiceImpl.getInstance().WMS_RecoilMaterialUse(wLoginUser, wItemID);
                }
                wIndex++;
            }
            // ⑤关联物料需求计划
            int wOrderID = wList.get(0).OrderID;
            int wPartID = wList.get(0).PartID;
            List<MRPMaterialPlan> wPList = wList.stream()
                    .filter(p -> p.OrderID == wOrderID && p.PartID == wPartID && p.Active == 1)
                    .collect(Collectors.toList());
            for (MRPMaterialPlan wMRPMaterialPlan : wPList) {
                wMRPMaterialPlan.Status = wMRPMaterialPlanStatus;
                wMRPMaterialPlan.EditID = wLoginUser.ID;
                wMRPMaterialPlan.EditTime = Calendar.getInstance();
                wMRPMaterialPlan.WMSPickDemandID = wDemandID;
                MRPMaterialPlanDAO.getInstance().Update(wLoginUser, wMRPMaterialPlan, wErrorCode);
            }
            // 推送物料需求计划
            WMSServiceImpl.getInstance().WMS_ManualPush(wLoginUser, wDemandID);
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    @Override
    public ServiceResult<APSSchedulingVersionBPM> APS_GetSchedulingVersionBPM(BMSEmployee wLoginUser, int wID) {
        ServiceResult<APSSchedulingVersionBPM> wResult = new ServiceResult<>();
        wResult.Result = new APSSchedulingVersionBPM();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            wResult.Result = (APSSchedulingVersionBPM) APSSchedulingVersionBPMDAO.getInstance()
                    .BPM_GetTaskInfo(wLoginUser, wID, "", wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<APSSchedulingVersionBPM>> APS_QuerySchedulingVersionBPMHistory(BMSEmployee wLoginUser,
                                                                                             int wID, String wCode,
                                                                                             int wUpFlowID,
                                                                                             int wFollowerID,
                                                                                             int wAPSShiftPeriod,
                                                                                             Calendar wStartTime,
                                                                                             Calendar wEndTime) {
        ServiceResult<List<APSSchedulingVersionBPM>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            String wFollower = "";
            if (wFollowerID > 0) {
                wFollower = String.valueOf(wFollowerID);
            }
            wResult.Result = APSSchedulingVersionBPMDAO.getInstance().SelectList(wLoginUser, wID, wCode, -1, wUpFlowID,
                    wFollower, "", wAPSShiftPeriod, -1, null, null, wStartTime, wEndTime, wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<BPMTaskBase>> APS_QuerySchedulingVersionBPMEmployeeAll(BMSEmployee wLoginUser,
                                                                                     int wAPSShiftPeriod,
                                                                                     int wTagTypes,
                                                                                     Calendar wStartTime,
                                                                                     Calendar wEndTime) {
        ServiceResult<List<BPMTaskBase>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            int wEventID = 0;
            switch (APSShiftPeriod.getEnumType(wAPSShiftPeriod)) {
                case Month:
                    wEventID = BPMEventModule.SCMonthAudit.getValue();
                    break;
                case Week:
                    wEventID = BPMEventModule.SCWeekAudit.getValue();
                    break;
                default:
                    break;
            }

            switch (TagTypes.getEnumType(wTagTypes)) {
                case Applicant:// 2发起
                    wResult.Result = APSSchedulingVersionBPMDAO.getInstance().BPM_GetSendTaskList(wLoginUser,
                            wLoginUser.ID,
                            wStartTime, wEndTime, wErrorCode);
                    break;
                case Dispatcher:// 1待做
                    wResult.Result = APSSchedulingVersionBPMDAO.getInstance().BPM_GetUndoTaskList(wLoginUser,
                            wLoginUser.ID,
                            wErrorCode);
                    break;
                case Approver:// 4已做
                    wResult.Result = APSSchedulingVersionBPMDAO.getInstance().BPM_GetDoneTaskList(wLoginUser,
                            wLoginUser.ID,
                            wStartTime, wEndTime, wErrorCode);
                    break;
                default:
                    break;
            }

            int wEventC = wEventID;
            wResult.Result = wResult.Result.stream().filter(p -> p.FlowType == wEventC && p.Status != 0)
                    .collect(Collectors.toList());

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<APSTaskPart>> APS_QuerySchedulingVersionItemDetails(BMSEmployee wLoginUser,
                                                                                  int wAPSSchedulingVersionBPMID) {
        ServiceResult<List<APSTaskPart>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            if (wAPSSchedulingVersionBPMID <= 0) {
                return wResult;
            }

            APSSchedulingVersionBPM wTask = (APSSchedulingVersionBPM) APSSchedulingVersionBPMDAO.getInstance()
                    .BPM_GetTaskInfo(wLoginUser, wAPSSchedulingVersionBPMID, "", wErrorCode);

            if (wTask == null || wTask.ID <= 0 || wTask.TaskPartIDList == null || wTask.TaskPartIDList.size() <= 0) {
                return wResult;
            }

            wResult.Result = APSTaskPartDAO.getInstance().SelectListByIDList(wLoginUser, wTask.TaskPartIDList,
                    wErrorCode);

            wResult.CustomResult.put("Info", wTask);

            List<OMSOrder> wOMSOrderList = new ArrayList<>();
            if (wResult.Result.size() > 0) {
                List<Integer> wOrderIDList = wResult.Result.stream().map(p -> p.OrderID).distinct()
                        .collect(Collectors.toList());
                wOMSOrderList = OMSOrderDAO.getInstance().SelectListByIDList(wLoginUser, wOrderIDList, wErrorCode);
            }
            wResult.CustomResult.put("OMSOrderList", wOMSOrderList);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<APSDayPlanAudit> APS_QueryDayPlanAudit(BMSEmployee wLoginUser, int wID) {
        ServiceResult<APSDayPlanAudit> wResult = new ServiceResult<>();
        wResult.Result = new APSDayPlanAudit();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wResult.Result = APSDayPlanAuditDAO.getInstance().SelectByID(wLoginUser, wID, wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> APS_CheckIsAuditor(BMSEmployee wLoginUser) {
        ServiceResult<Integer> wResult = new ServiceResult<>();
        wResult.FaultCode = "";
        try {
            if (APSConstans.GetLFSWorkAreaCheckerList().stream().noneMatch(p -> p.LeaderIDList != null
                    && p.LeaderIDList.size() > 0 && p.LeaderIDList.stream().anyMatch(q -> q == wLoginUser.ID))) {
                wResult.FaultCode += "提示：登录者不是工区主管!";
                return wResult;
            }
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> APS_ReSetTaskStep(BMSEmployee wLoginUser, int wAPSTaskStepID) {
        ServiceResult<Integer> wResult = new ServiceResult<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            wResult.Result = APSTaskStepDAO.getInstance().ReSet(wLoginUser, wAPSTaskStepID, wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public synchronized ServiceResult<Integer> OMS_BatchInPlantConfirm(BMSEmployee wLoginUser,
                                                                       List<OMSOrder> wDataList) {
        ServiceResult<Integer> wResult = new ServiceResult<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            if (wDataList.stream().anyMatch(p -> p.Status != OMSOrderStatus.ReceivedTelegraph.getValue())) {
                wResult.FaultCode += "提示：请选择状态为“已收电报”的订单!";
                return wResult;
            }

            String wNotDisplayProductChar = Configuration.readConfigString("NotDisplayProductChar", "config/config");
            List<String> wChartList = StringUtils.parseList(wNotDisplayProductChar.split(","));

            for (OMSOrder wOrder : wDataList) {

                // 验证标准BOM
                boolean wFlag = MSSBOMItemDAO.getInstance().JudgeIsHasCurrent(wLoginUser, wOrder.RouteID, wErrorCode);
                if (!wFlag) {
                    wResult.FaultCode += StringUtils.Format("提示：【{0}】绑定的工艺BOP无对应版本的当前标准BOM!", wOrder.PartNo);
                    return wResult;
                }

                // 创建进厂确认单
                SFCOrderForm wSFCOrderForm = new SFCOrderForm(0, wOrder.ID, wOrder.OrderNo, wOrder.PartNo,
                        wLoginUser.ID, wLoginUser.Name, Calendar.getInstance(), wLoginUser.ID, wLoginUser.Name,
                        Calendar.getInstance(), 2, SFCOrderFormType.InConfirm.getValue(), wOrder.LineName,
                        wOrder.ProductNo, wOrder.BureauSection);
                wResult.Result = SFCOrderFormDAO.getInstance().Update(wLoginUser, wSFCOrderForm, wErrorCode);
                // 修改订单状态为已进场
                wOrder.Status = OMSOrderStatus.EnterFactoryed.getValue();
                wOrder.RealReceiveDate = Calendar.getInstance();

                // 获取最新的ERPID(排序字段)
                wOrder.ERPID = OMSOrderDAO.getInstance().GetMaxERPID(wLoginUser, wErrorCode);

                OMSOrderDAO.getInstance().Update(wLoginUser, wOrder, wErrorCode);

                // “广州铁路轨道装备有限公司”局段的车辆不绑定到看板上
                if (wOrder.CustomerID == 43 || wOrder.ProductNo.contains("XS")) {
                    continue;
                }

                // 剔除已配置的不展示车型
                if (wChartList.stream().anyMatch(p -> wOrder.ProductNo.contains(p))) {
                    continue;
                }
                if (wOrder.OrderType != OMSOrderType.CheTi.getValue())
                    continue;

                // 将车绑定到厂线上(分多节情况)
                List<MTCSectionInfo> wSectionList = WDWServiceImpl.getInstance()
                        .MTC_QuerySectionInfoList(wLoginUser, wOrder.ProductID).List(MTCSectionInfo.class);
                if (wSectionList != null && wSectionList.size() > 1) {
                    for (MTCSectionInfo wSectionInfo : wSectionList) {
                        String wPNo = StringUtils.Format("{0}-{1}", wOrder.PartNo, wSectionInfo.Name);

                        WDWServiceImpl.getInstance().WDW_BindCarToPlant(wLoginUser, wPNo);
                    }
                } else {
                    WDWServiceImpl.getInstance().WDW_BindCarToPlant(wLoginUser, wOrder.PartNo);
                }
            }

            // 创建并推送台车BOM
            for (OMSOrder omsOrder : wDataList) {
                // 查询台车BOM创建日志，若存在，则不创建台车bom
                List<APSBOMLog> apsbomLogs = APSBOMLogDAO.getInstance().SelectList(wLoginUser, -1, -1, -1, -1,
                        omsOrder.ID,
                        -1, null, null, wErrorCode);
                if (apsbomLogs.size() == 0) {
                    ExecutorService wES = Executors.newFixedThreadPool(1);
                    wES.submit(() -> APSServiceImpl.getInstance().APS_CreateBomItemByOrder(BaseDAO.SysAdmin,
                            omsOrder.ID));
                    wES.shutdown();
                }
            }

            // 修改订单的工艺路线为最新的
            TaskTimerUtils.AddTask("UpdateRoute", () -> {
                UpdateRoute(wLoginUser, wDataList);
            }, 2000);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    /**
     * 修改订单的工艺路线为最新的
     */
    private void UpdateRoute(BMSEmployee wLoginUser, List<OMSOrder> wDataList) {
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            for (OMSOrder omsOrder : wDataList) {
                int wRouteID = OMSOrderDAO.getInstance().GetRouteIDByOrderID(wLoginUser, omsOrder.ID, wErrorCode);
                if (wRouteID <= 0) {
                    continue;
                }
                omsOrder.RouteID = wRouteID;
                OMSOrderDAO.getInstance().Update(wLoginUser, omsOrder, wErrorCode);

                // 触发预检和机车一级解体任务
                TriggerPreCheckTask(wLoginUser, omsOrder);
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    /**
     * 触发预检和机车一级解体任务
     */
    private void TriggerPreCheckTask(BMSEmployee wLoginUser, OMSOrder omsOrder) {
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            List<APSTriggerPart> wList = APSTriggerPartDAO.getInstance().SelectList(wLoginUser, -1, omsOrder.ProductID,
                    omsOrder.LineID, -1, 1, wErrorCode);
            if (wList == null || wList.size() <= 0) {
                return;
            }

            Calendar wStartTime = Calendar.getInstance();
            wStartTime.set(Calendar.getInstance().get(Calendar.YEAR), Calendar.getInstance().get(Calendar.MONTH),
                    Calendar.getInstance().get(Calendar.DATE), 8, 0, 0);
            Calendar wEndTime = (Calendar) wStartTime.clone();
            wEndTime.add(Calendar.HOUR_OF_DAY, 12);

            SimpleDateFormat wSDF = new SimpleDateFormat("yyyyMMdd");
            int wShiftID = Integer.parseInt(wSDF.format(Calendar.getInstance().getTime()));

            Calendar wBaseTime = Calendar.getInstance();
            wBaseTime.set(2000, 0, 1, 0, 0, 0);

            // 触发工位任务
            for (APSTriggerPart apsTriggerPart : wList) {
                // 查询是否存在工位任务，若存在继续
                List<APSTaskPart> wExsitList = APSTaskPartDAO.getInstance().SelectList(wLoginUser, -1, omsOrder.ID, -1,
                        -1, apsTriggerPart.PartID, 1, APSShiftPeriod.Week.getValue(), null, -1, null, null, wErrorCode);
                if (wExsitList.size() > 0) {
                    continue;
                }

                APSTaskPart wAPSTaskPart = new APSTaskPart(0, omsOrder.ID, omsOrder.PartNo, 0, omsOrder.LineID,
                        apsTriggerPart.PartID, wShiftID, wLoginUser.ID, APSShiftPeriod.Week.getValue(),
                        Calendar.getInstance(), wStartTime, wEndTime, omsOrder.OrderNo, 0, wLoginUser.Name, 1, 2,
                        Calendar.getInstance(), omsOrder.CustomerID, omsOrder.OrderNo, omsOrder.RouteID, wLoginUser.ID,
                        wLoginUser.Name);
                wAPSTaskPart.FinishWorkTime = wBaseTime;
                wAPSTaskPart.StartWorkTime = wBaseTime;
                wAPSTaskPart.ProductNo = omsOrder.ProductNo;
                wAPSTaskPart.ID = (int) APSTaskPartDAO.getInstance().Update(wLoginUser, wAPSTaskPart, wErrorCode);
                if (wAPSTaskPart.ID <= 0) {
                    continue;
                }
                // 触发工序任务
                List<FPCRoutePartPoint> wRoutePartPointList = FMCServiceImpl.getInstance()
                        .FPC_QueryRoutePartPointListByRouteID(wLoginUser, omsOrder.RouteID, apsTriggerPart.PartID)
                        .List(FPCRoutePartPoint.class);
                for (FPCRoutePartPoint wFPCRoutePartPoint : wRoutePartPointList) {
                    List<APSTaskStep> wExsitStepList = APSTaskStepDAO.getInstance().SelectList(wLoginUser, -1,
                            omsOrder.ID, -1, -1, -1, -1, apsTriggerPart.PartID, wFPCRoutePartPoint.PartPointID, -1, 1,
                            null, null, null, null, wErrorCode);
                    if (wExsitStepList.size() > 0) {
                        continue;
                    }

                    APSTaskStep wAPSTaskStep = new APSTaskStep();

                    wAPSTaskStep.ID = 0;
                    wAPSTaskStep.Active = 1;
                    wAPSTaskStep.LineID = wAPSTaskPart.LineID;
                    wAPSTaskStep.MaterialNo = wAPSTaskPart.MaterialNo;
                    wAPSTaskStep.OrderID = wAPSTaskPart.OrderID;
                    wAPSTaskStep.PartID = wAPSTaskPart.PartID;
                    wAPSTaskStep.PartNo = wAPSTaskPart.PartNo;
                    wAPSTaskStep.PlanerID = wLoginUser.ID;
                    wAPSTaskStep.ProductNo = wAPSTaskPart.ProductNo;
                    wAPSTaskStep.ShiftID = wShiftID;
                    wAPSTaskStep.Status = APSTaskStatus.Issued.getValue();
                    wAPSTaskStep.StepID = wFPCRoutePartPoint.PartPointID;
                    wAPSTaskStep.TaskPartID = wAPSTaskPart.ID;
                    wAPSTaskStep.TaskLineID = wAPSTaskPart.TaskLineID;
                    wAPSTaskStep.TaskText = wAPSTaskPart.TaskText;
                    wAPSTaskStep.WorkHour = 0;
                    wAPSTaskStep.WorkShopID = wAPSTaskPart.WorkShopID;
                    wAPSTaskStep.StartTime = wBaseTime;
                    wAPSTaskStep.EndTime = wBaseTime;
                    wAPSTaskStep.ReadyTime = wBaseTime;
                    wAPSTaskStep.CreateTime = Calendar.getInstance();
                    wAPSTaskStep.PlanStartTime = wStartTime;
                    wAPSTaskStep.PlanEndTime = wEndTime;

                    APSTaskStepDAO.getInstance().Update(wLoginUser, wAPSTaskStep, wErrorCode);
                }
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    @Override
    public ServiceResult<List<APSTaskPart>> APS_QueryWorkHourList(BMSEmployee wLoginUser, Calendar wStartTime,
                                                                  Calendar wEndTime, int wOrderID) {
        ServiceResult<List<APSTaskPart>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            wResult.Result = APSTaskPartDAO.getInstance().SelectList(wLoginUser, -1, wOrderID, -1, -1, -1, 1,
                    APSShiftPeriod.Week.getValue(), null, -1, wStartTime, wEndTime, wErrorCode);

            if (APSConstans.GetBMSDepartment(wLoginUser.DepartmentID).Type == BMSDepartmentType.Class.getValue()) {
                List<FMCWorkCharge> wChargeList = APSConstans.GetFMCWorkChargeList().stream()
                        .filter(p -> p.Active == 1 && p.ClassID == wLoginUser.DepartmentID)
                        .collect(Collectors.toList());
                wResult.Result = wResult.Result.stream()
                        .filter(p -> wChargeList.stream().anyMatch(q -> q.StationID == p.PartID))
                        .collect(Collectors.toList());
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> APS_Delete(BMSEmployee wLoginUser, int wOrderID, int wPartID) {
        ServiceResult<Integer> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            List<APSTaskStep> wList = APSTaskStepDAO.getInstance().SelectList(wLoginUser, -1, wOrderID, -1, -1, -1, -1,
                    wPartID, -1, -1, -1, null, null, null, null, wErrorCode);

            List<APSTaskStep> wOneList = new ArrayList<>();
            for (APSTaskStep wAPSTaskStep : wList) {
                if (wOneList.stream().noneMatch(p -> p.StepID == wAPSTaskStep.StepID)) {
                    if (wList.stream().anyMatch(p -> p.StepID == wAPSTaskStep.StepID && p.Status != 1)) {
                        wOneList.add(wList.stream().filter(p -> p.StepID == wAPSTaskStep.StepID && p.Status != 1)
                                .findFirst().get());
                    } else {
                        wOneList.add(wAPSTaskStep);
                    }
                }
            }

            List<APSTaskStep> wRepeatList = wList.stream().filter(p -> wOneList.stream().noneMatch(q -> q.ID == p.ID))
                    .collect(Collectors.toList());
            if (wRepeatList.size() > 0) {
                APSTaskStepDAO.getInstance().DeleteList(wLoginUser, wRepeatList, wErrorCode);
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<SFCTaskStepInfo>> APS_GetCarStationList(BMSEmployee wLoginUser, Calendar wTaskDate,
                                                                      int wWorkAreaID) {
        ServiceResult<List<SFCTaskStepInfo>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            // ①将wTaskDate转换为一天的开始时间和结束时间
            Calendar wStartTime = (Calendar) wTaskDate.clone();
            wStartTime.set(Calendar.HOUR_OF_DAY, 0);
            wStartTime.set(Calendar.MINUTE, 0);
            wStartTime.set(Calendar.SECOND, 0);
            Calendar wEndTime = (Calendar) wTaskDate.clone();
            wEndTime.set(Calendar.HOUR_OF_DAY, 23);
            wEndTime.set(Calendar.MINUTE, 59);
            wEndTime.set(Calendar.SECOND, 59);
            // ①获取工位任务列表
            boolean wIsAll = CoreServiceImpl.getInstance()
                    .BMS_CheckPowerByAuthorityID(wLoginUser.CompanyID, wLoginUser.ID, 501002, 0, 0)
                    .Info(Boolean.class);
            List<APSTaskPart> wList = APSTaskPartDAO.getInstance().SelectDispatchList(wLoginUser, wStartTime, wEndTime,
                    wIsAll, wErrorCode);

            // 有所有权限的人，提供工区筛选
            if (wIsAll && wWorkAreaID > 0) {
                // ①获取工区工位
                List<LFSWorkAreaStation> wWSList = new ArrayList<>(APSConstans.GetLFSWorkAreaStationList().values());
                // ②筛选工位任务
                if (wWSList.size() > 0) {
                    wList = wList.stream()
                            .filter(p -> wWSList.stream().anyMatch(
                                    q -> q.Active == 1 && q.WorkAreaID == wWorkAreaID && q.StationID == p.PartID))
                            .collect(Collectors.toList());
                }
            } else {
                // 筛选车型、班组、工位
                List<BMSProductClassPart> wPCPList = BMSWorkChargeItemDAO.getInstance()
                        .GetProductClassPartList(wLoginUser, wLoginUser.DepartmentID, wErrorCode);
                if (wPCPList.size() > 0) {
                    wList = wList.stream()
                            .filter(p -> wPCPList.stream()
                                    .anyMatch(q -> q.ProductNo.equals(p.ProductNo) && q.PartID == p.PartID))
                            .collect(Collectors.toList());
                }
            }

            // 根据班组查询班组工位工序配置
            List<BMSWorkChargeStep> wBMSWorkChargeStepList = LFSServiceImpl.getInstance()
                    .BMS_QueryWorkChargeStepList(wLoginUser, -1, wLoginUser.DepartmentID,
                            -1, -1, -1)
                    .List(BMSWorkChargeStep.class);

            // ②转换为工位信息列表
            List<BMSWorkChargeStep> wStepConfigList = new ArrayList<>();
            for (APSTaskPart wAPSTaskPart : wList) {
                // 判断日计划是否已下达
                if (!APSTaskPartDAO.getInstance().IsIssueDayPlan(wLoginUser, wAPSTaskPart.ID, wErrorCode)) {
                    continue;
                }
                // 已完工的任务剔除
                if (wAPSTaskPart.OrderStatus >= 5) {
                    continue;
                }

                // 通过工位、车型筛选工序配置
                wStepConfigList = wBMSWorkChargeStepList.stream().filter(p -> p.StationID == wAPSTaskPart.PartID)
                        .collect(Collectors.toList());

                SFCTaskStepInfo wInfo = APSTaskPartDAO.getInstance().SelectToDoAndDone(wLoginUser, wAPSTaskPart.ID,
                        wStepConfigList,
                        wErrorCode);
                SFCTaskStepInfo wSFCTaskStepInfo = new SFCTaskStepInfo();
                wSFCTaskStepInfo.Dispatched = wInfo.Dispatched;
                wSFCTaskStepInfo.OrderID = wAPSTaskPart.OrderID;
                wSFCTaskStepInfo.OrderNo = wAPSTaskPart.OrderNo;
                wSFCTaskStepInfo.PartNo = wAPSTaskPart.PartNo;
                wSFCTaskStepInfo.StationID = wAPSTaskPart.PartID;
                wSFCTaskStepInfo.StationName = wAPSTaskPart.PartName;
                wSFCTaskStepInfo.ToDispatch = wInfo.ToDispatch;
                wSFCTaskStepInfo.Status = wInfo.ToDispatch == 0 ? 1 : 0;
                wSFCTaskStepInfo.OrderStatus = wAPSTaskPart.OrderStatus;
                wSFCTaskStepInfo.LineName = wAPSTaskPart.LineName;
                wSFCTaskStepInfo.CustomerName = wAPSTaskPart.CustomerName;

                wResult.Result.add(wSFCTaskStepInfo);
            }
            // ①获取质量工位数据
            List<APSTaskStep> wTaskStepList = APSTaskStepDAO.getInstance().SelectFinalAndOutList(wLoginUser, wStartTime,
                    wEndTime, wErrorCode);
            // ②根据订单和工位去重
            wTaskStepList = new ArrayList<>(wTaskStepList.stream()
                    .collect(Collectors.toMap(p -> p.getOrderID() + "_" + p.getPartID(), p -> p, (o1, o2) -> o1))
                    .values());

            // ③遍历获取数据
            for (APSTaskStep wAPSTaskStep : wTaskStepList) {
                // 已完工的任务剔除
                if (wAPSTaskStep.OrderStatus >= 5) {
                    continue;
                }

                List<APSTaskStep> wAllTaskStepList = APSTaskStepDAO.getInstance().SelectList(wLoginUser, -1,
                        wAPSTaskStep.OrderID, -1, -1, -1, -1, wAPSTaskStep.PartID, -1, -1, 1, null, null, null, null,
                        wErrorCode);
                SFCTaskStepInfo wSFCTaskStepInfo = new SFCTaskStepInfo();
                wSFCTaskStepInfo.Dispatched = (int) wAllTaskStepList.stream().filter(p -> p.IsDispatched).count();
                wSFCTaskStepInfo.OrderID = wAPSTaskStep.OrderID;
                wSFCTaskStepInfo.OrderNo = wAPSTaskStep.OrderNo;
                wSFCTaskStepInfo.PartNo = wAPSTaskStep.PartNo;
                wSFCTaskStepInfo.StationID = wAPSTaskStep.PartID;
                wSFCTaskStepInfo.StationName = wAPSTaskStep.PartName;
                wSFCTaskStepInfo.ToDispatch = (int) wAllTaskStepList.stream().filter(p -> !p.IsDispatched).count();
                wSFCTaskStepInfo.Status = wSFCTaskStepInfo.ToDispatch == 0 ? 1 : 0;
                wSFCTaskStepInfo.OrderStatus = wAPSTaskStep.OrderStatus;
                wSFCTaskStepInfo.LineName = wAPSTaskStep.LineName;
                wSFCTaskStepInfo.CustomerName = wAPSTaskStep.CustomerName;

                wResult.Result.add(wSFCTaskStepInfo);
            }
            // ④去重
            wResult.Result = wResult.Result.stream()
                    .collect(Collectors.collectingAndThen(Collectors.toCollection(
                                    () -> new TreeSet<>(Comparator.comparing(o -> o.getPartNo() + ";" + o.getStationName()))),
                            ArrayList::new));

            // ⑤工区赋值
            if (wResult.Result.size() > 0) {
                List<LFSWorkAreaStation> wWorkStationList = new ArrayList<>(
                        APSConstans.GetLFSWorkAreaStationList().values());
                wWorkStationList = wWorkStationList.stream().filter(p -> p.Active == 1 && p.WorkAreaID > 0)
                        .collect(Collectors.toList());
                for (SFCTaskStepInfo wSFCTaskStepInfo : wResult.Result) {
                    if (wWorkStationList.stream().noneMatch(p -> p.StationID == wSFCTaskStepInfo.StationID)) {
                        continue;
                    }

                    LFSWorkAreaStation wWorkArea = wWorkStationList.stream()
                            .filter(p -> p.StationID == wSFCTaskStepInfo.StationID).findFirst().get();
                    wSFCTaskStepInfo.AreaID = wWorkArea.WorkAreaID;
                    wSFCTaskStepInfo.AreaName = APSConstans.GetBMSDepartmentName(wWorkArea.WorkAreaID);
                }
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<APSTaskStep>> APS_QueryTaskStepListByOrder(BMSEmployee wLoginUser, Calendar wTaskDate,
                                                                         int wOrderID, int wPartID, String wPartNo) {
        ServiceResult<List<APSTaskStep>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            // ③通过时间段和工位列表查询工位任务集合
            wResult.Result = APSTaskStepDAO.getInstance().SelectListByOrder(wLoginUser, wOrderID, wPartID, wPartNo,
                    wErrorCode);
            // 去重
            wResult.Result = new ArrayList<>(wResult.Result.stream()
                    .collect(Collectors.toMap(APSTaskStep::getID, account -> account, (k1, k2) -> k2)).values());

            if (wResult.Result.size() <= 0) {
                return wResult;
            }

            // 根据工序配置，筛选该班组长管理的工序任务列表
            List<BMSWorkChargeStep> wBMSWorkChargeStepList = LFSServiceImpl.getInstance()
                    .BMS_QueryWorkChargeStepList(wLoginUser, -1, wLoginUser.DepartmentID,
                            wPartID, wResult.Result.get(0).ProductID, -1)
                    .List(BMSWorkChargeStep.class);
            if (wBMSWorkChargeStepList != null && wBMSWorkChargeStepList.size() > 0) {
                wResult.Result = wResult.Result.stream()
                        .filter(p -> wBMSWorkChargeStepList.stream().anyMatch(q -> q.PartPointID == p.StepID))
                        .collect(Collectors.toList());
            }

            /*
             * 默认人员返回(没派工记录时默认返回)
             */
            Map<Integer, List<Integer>> wPersonMap = SFCServiceImpl.getInstance().SFC_QueryStepPersonMap(wLoginUser,
                    wResult.Result).Result;

            List<Integer> wAPSTaskstepIDList = wResult.Result.stream().map(p -> p.ID).collect(Collectors.toList());
            List<SFCTaskStep> wList = SFCTaskStepDAO.getInstance().SelectListByTaskStepIDList(wLoginUser,
                    wAPSTaskstepIDList, SFCTaskStepType.Step.getValue(), wErrorCode);

            // 查询自检、互检、专检单的状态
            List<SFCTaskIPT> wSFCTaskIPTList = SFCTaskStepDAO.getInstance().GetCheckTaskStatusList(wLoginUser,
                    wAPSTaskstepIDList, wErrorCode);

            for (APSTaskStep wAPSTaskStep : wResult.Result) {
                // 自检互检专检状态
                if (wSFCTaskIPTList.stream().anyMatch(p -> p.TaskStepID == wAPSTaskStep.ID && p.TaskType == 6)) {
                    wAPSTaskStep.SelfStatus = wSFCTaskIPTList.stream()
                            .filter(p -> p.TaskStepID == wAPSTaskStep.ID && p.TaskType == 6).findFirst().get().Status;
                }
                if (wSFCTaskIPTList.stream().anyMatch(p -> p.TaskStepID == wAPSTaskStep.ID && p.TaskType == 12)) {
                    wAPSTaskStep.MutualStatus = wSFCTaskIPTList.stream()
                            .filter(p -> p.TaskStepID == wAPSTaskStep.ID && p.TaskType == 12).findFirst().get().Status;
                }
                if (wSFCTaskIPTList.stream().anyMatch(p -> p.TaskStepID == wAPSTaskStep.ID && p.TaskType == 13)) {
                    wAPSTaskStep.SpecialStatus = wSFCTaskIPTList.stream()
                            .filter(p -> p.TaskStepID == wAPSTaskStep.ID && p.TaskType == 13).findFirst().get().Status;
                }

                List<SFCTaskStep> wTempList = wList.stream().filter(p -> p.TaskStepID == wAPSTaskStep.ID)
                        .collect(Collectors.toList());

                if (wAPSTaskStep.OperatorList != null && wAPSTaskStep.OperatorList.size() > 0) {
                    wAPSTaskStep.Operators = GetUserNames(wAPSTaskStep.OperatorList);
                    continue;
                }

                if (wTempList.size() > 0) {
                    wAPSTaskStep.OperatorList = wTempList.stream().map(p -> p.OperatorID).collect(Collectors.toList());
                    continue;
                }

                if (!wPersonMap.containsKey(wAPSTaskStep.ID)) {
                    continue;
                }
                wAPSTaskStep.OperatorList = wPersonMap.get(wAPSTaskStep.ID);
                wAPSTaskStep.Operators = GetUserNames(wPersonMap.get(wAPSTaskStep.ID));
            }

            // 筛选激活的数据
            wResult.Result = wResult.Result.stream().filter(p -> p.Active == 1).collect(Collectors.toList());

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<APSTaskPart>> APS_QueryMoreTaskPartList(BMSEmployee wLoginUser,
                                                                      List<Integer> wOrderIDList, Calendar wStartTime, Calendar wEndTime, int wAPSShiftPeriod) {
        ServiceResult<List<APSTaskPart>> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wResult.Result = APSTaskPartDAO.getInstance().SelectListByOrderListAndTime(wLoginUser, wOrderIDList,
                    wStartTime, wEndTime, wAPSShiftPeriod, wErrorCode);

            // 工位排序
            OrderPart(wResult.Result);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(StringUtils.Format("{0} {1} ex：{2}",
                    "APSServiceImpl", "APS_QueryTaskPartList", e.toString()));
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<APSTaskStepInfo>> APS_QueryTaskStepInfo(BMSEmployee wLoginUser, Calendar wStartTime,
                                                                      Calendar wEndTime, List<Integer> wClassIDList,
                                                                      List<Integer> wPartIDList,
                                                                      List<Integer> wStatusList,
                                                                      int wIsDisPatched) {
        ServiceResult<List<APSTaskStepInfo>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            Calendar wBaseTime = Calendar.getInstance();
            wBaseTime.set(2010, 1, 1);
            if (wEndTime.compareTo(wBaseTime) < 0) {
                wEndTime.set(3000, 1, 1);
            }

            if (wPartIDList == null || wPartIDList.size() <= 0
                    || (wPartIDList.size() == 1 && wPartIDList.get(0) == -1)) {
                wPartIDList = APSServiceImpl.getInstance().APS_QueryStationList(wLoginUser).Result.stream()
                        .map(p -> p.ID).collect(Collectors.toList());
            }
            if (wClassIDList == null || wClassIDList.size() <= 0
                    || (wClassIDList.size() == 1 && wClassIDList.get(0) == -1)) {
                wClassIDList = APSServiceImpl.getInstance().APS_QueryClassList(wLoginUser).Result.stream()
                        .map(p -> p.ID).collect(Collectors.toList());
            }
            if (wStatusList == null || wStatusList.size() <= 0
                    || (wStatusList.size() == 1 && wStatusList.get(0) == -1)) {
                wStatusList = new ArrayList<>();
            }

            wResult.Result = APSTaskStepDAO.getInstance().QueryAPSTaskStepInfoList(wLoginUser, wStartTime, wEndTime,
                    wClassIDList, wPartIDList, wStatusList, wIsDisPatched, wErrorCode);

            List<LFSWorkAreaStation> wList = APSConstans.GetLFSWorkAreaStationList().values().stream()
                    .filter(p -> p.Active == 1).collect(Collectors.toList());
            for (APSTaskStepInfo wAPSTaskStepInfo : wResult.Result) {
                if (wList.stream().anyMatch(p -> p.StationID == wAPSTaskStepInfo.PartID)) {
                    LFSWorkAreaStation wItem = wList.stream().filter(p -> p.StationID == wAPSTaskStepInfo.PartID)
                            .findFirst().get();
                    wAPSTaskStepInfo.AreaID = wItem.WorkAreaID;
                    wAPSTaskStepInfo.Area = APSConstans.GetBMSDepartmentName(wItem.WorkAreaID);
                }
            }

            // 排序
            if (wResult.Result.size() > 0) {
                wResult.Result
                        .sort(Comparator.comparing(APSTaskStepInfo::getPartNo).thenComparing(APSTaskStepInfo::getID));
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<BMSDepartment>> APS_QueryClassList(BMSEmployee wLoginUser) {
        ServiceResult<List<BMSDepartment>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            List<BMSDepartment> wList = APSConstans.GetBMSDepartmentList().values().stream()
                    .filter(p -> p.Active == 1 && p.Type == 3).collect(Collectors.toList());
            if (wList.stream().anyMatch(p -> p.ID == wLoginUser.DepartmentID)) {
                wResult.Result = wList.stream().filter(p -> p.ID == wLoginUser.DepartmentID)
                        .collect(Collectors.toList());
                wResult.CustomResult.put("IsAllClass", false);
            } else {
                wResult.Result = wList;
                wResult.CustomResult.put("IsAllClass", true);
            }

            ServiceResult<List<FPCPart>> wSR = APSServiceImpl.getInstance().APS_QueryStationList(wLoginUser);
            boolean wIsAllPart = (boolean) wSR.Get("IsAllPart");
            wResult.CustomResult.put("IsAllPart", wIsAllPart);
            wResult.CustomResult.put("PartList", wSR.Result);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<FPCPart>> APS_QueryStationList(BMSEmployee wLoginUser) {
        ServiceResult<List<FPCPart>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            List<FMCWorkCharge> wList = APSConstans.GetFMCWorkChargeList().stream()
                    .filter(p -> p.ClassID == wLoginUser.DepartmentID).collect(Collectors.toList());
            if (wList.size() > 0) {
                for (FMCWorkCharge wFMCWorkCharge : wList) {
                    wResult.Result.add(APSConstans.GetFPCPart(wFMCWorkCharge.StationID));
                }
                wResult.CustomResult.put("IsAllPart", false);
            } else {
                wResult.Result = APSConstans.GetFPCPartList().values().stream().filter(p -> p.Active == 1)
                        .collect(Collectors.toList());
                wResult.CustomResult.put("IsAllPart", true);
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<APSTaskStepDetails>> APS_QueryTransInfo(BMSEmployee wLoginUser, int wAPSTaskPartID) {
        ServiceResult<List<APSTaskStepDetails>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            wResult.Result = APSTaskStepDAO.getInstance().SelectAPSTaskStepDetails(wLoginUser, wAPSTaskPartID,
                    wErrorCode);

            if (wResult.Result.size() > 0) {
                int productID = wResult.Result.get(0).ProductID;
                int partID = wResult.Result.get(0).PartID;
                List<Integer> wStepIDList = wResult.Result.stream().map(p -> p.PartPointID).distinct()
                        .collect(Collectors.toList());
                List<Integer> wPicIDList = APSTaskStepPlanDAO.getInstance().SelectPicStepIDList(wLoginUser, productID,
                        partID, wStepIDList, wErrorCode);
                for (APSTaskStepDetails wAPSTaskStepDetails : wResult.Result) {
                    if (wPicIDList.stream().noneMatch(p -> p == wAPSTaskStepDetails.PartPointID)) {
                        continue;
                    }
                    wAPSTaskStepDetails.TSize = 1;
                    APSTaskStepDetails wInfo = APSTaskStepDAO.getInstance().GetTaskStatus(wLoginUser,
                            wAPSTaskStepDetails.ID, wErrorCode);
                    wAPSTaskStepDetails.SelfFSize = wInfo.STaskStatus == 2 ? 1 : 0;
                    wAPSTaskStepDetails.MFSize = wInfo.MTaskStatus == 2 ? 1 : 0;
                    wAPSTaskStepDetails.SFSize = wInfo.SpTaskStatus == 2 ? 1 : 0;
                }
            }

            wResult.CustomResult.put("APSTaskPart",
                    APSTaskPartDAO.getInstance().SelectByID(wLoginUser, wAPSTaskPartID, wErrorCode));

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<APSTaskStep>> APS_CreateTaskStepByShiftDateNew(BMSEmployee wLoginUser,
                                                                             Calendar wShiftDate) {
        ServiceResult<List<APSTaskStep>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            Calendar wShiftEnd = CalendarUtil.GetDate(wShiftDate);
            wShiftEnd.set(Calendar.HOUR_OF_DAY, 23);
            wShiftEnd.set(Calendar.MINUTE, 59);
            wShiftEnd.set(Calendar.SECOND, 59);

            // 工位详情
            List<APSTaskPartDetails> wAPSTaskPartDetailsList = APSTaskPartDAO.getInstance()
                    .SelectAPSTaskPartDetailsList(wLoginUser, wShiftEnd, wErrorCode);
            // 工序详情
            wResult.Result = APSTaskStepDAO.getInstance().SelectAPSTaskStepList(wLoginUser, wShiftEnd, wErrorCode);
            // 筛选排了计划的工序计划
            wResult.Result = wResult.Result.stream().filter(p -> wShiftEnd.compareTo(p.PlanStartTime) > 0)
                    .collect(Collectors.toList());
            // 订单详情
            List<OMSOrder> wOrderList = new ArrayList<>();
            if (wAPSTaskPartDetailsList.size() > 0) {
                wOrderList = OMSOrderDAO.getInstance().SelectListByIDList(wLoginUser,
                        wAPSTaskPartDetailsList.stream().map(p -> p.OrderID).collect(Collectors.toList()), wErrorCode);
            }
            // 重新赋值工位任务
            if (wAPSTaskPartDetailsList.size() > 0) {
                List<APSTaskPart> wTaskPartList = APSTaskPartDAO.getInstance().SelectListByIDList(wLoginUser,
                        wAPSTaskPartDetailsList.stream().map(p -> p.APSTaskPart.ID).collect(Collectors.toList()),
                        wErrorCode);
                for (APSTaskPartDetails wAPSTaskPartDetails : wAPSTaskPartDetailsList) {
                    if (wTaskPartList.stream().anyMatch(p -> p.ID == wAPSTaskPartDetails.APSTaskPart.ID)) {
                        wAPSTaskPartDetails.APSTaskPart = wTaskPartList.stream()
                                .filter(p -> p.ID == wAPSTaskPartDetails.APSTaskPart.ID).findFirst().get();
                    }
                }
            }
            // 剔除没有工序的工位
            wAPSTaskPartDetailsList.removeIf(
                    p -> wResult.Result.stream().noneMatch(q -> q.OrderID == p.OrderID && q.PartID == p.PartID));
            // 返回数据
            wResult.CustomResult.put("OrderList", wOrderList);
            wResult.CustomResult.put("TaskPartList", wAPSTaskPartDetailsList);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<APSPartNoDetails>> APS_QueryPartNoDetailsNew(BMSEmployee wLoginUser, Calendar wStartTime,
                                                                           Calendar wEndTime, int wWorkAreaID) {
        ServiceResult<List<APSPartNoDetails>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            // 今日时间
            Calendar wTodaySTime = Calendar.getInstance();
            wTodaySTime.set(Calendar.HOUR_OF_DAY, 0);
            wTodaySTime.set(Calendar.MINUTE, 0);
            wTodaySTime.set(Calendar.SECOND, 0);
            Calendar wTodayETime = Calendar.getInstance();
            wTodayETime.set(Calendar.HOUR_OF_DAY, 23);
            wTodayETime.set(Calendar.MINUTE, 59);
            wTodayETime.set(Calendar.SECOND, 59);

            Calendar wBaseTime = Calendar.getInstance();
            wBaseTime.set(2010, 0, 1, 0, 0, 0);
            if (wStartTime.compareTo(wBaseTime) < 0) {
                wStartTime = wTodaySTime;
            }
            if (wEndTime.compareTo(wBaseTime) < 0) {
                wEndTime = wTodayETime;
            }

            wResult.Result = APSTaskStepDAO.getInstance().SelectAPSPartNoDetailsList(wLoginUser, wStartTime, wEndTime,
                    wWorkAreaID, wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<APSWorkAreaDetails>> APS_QueryAreaDetailsNew(BMSEmployee wLoginUser, Calendar wStartTime,
                                                                           Calendar wEndTime, int wOrderID,
                                                                           int wWorkAreaID) {
        ServiceResult<List<APSWorkAreaDetails>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            // 今日时间
            Calendar wTodaySTime = Calendar.getInstance();
            wTodaySTime.set(Calendar.HOUR_OF_DAY, 0);
            wTodaySTime.set(Calendar.MINUTE, 0);
            wTodaySTime.set(Calendar.SECOND, 0);
            Calendar wTodayETime = Calendar.getInstance();
            wTodayETime.set(Calendar.HOUR_OF_DAY, 23);
            wTodayETime.set(Calendar.MINUTE, 59);
            wTodayETime.set(Calendar.SECOND, 59);

            Calendar wBaseTime = Calendar.getInstance();
            wBaseTime.set(2010, 0, 1, 0, 0, 0);
            if (wStartTime.compareTo(wBaseTime) < 0) {
                wStartTime = wTodaySTime;
            }
            if (wEndTime.compareTo(wBaseTime) < 0) {
                wEndTime = wTodayETime;
            }

            wResult.Result = APSTaskStepDAO.getInstance().SelectAPSWorkAreaDetailsList(wLoginUser, wStartTime, wEndTime,
                    wOrderID, wErrorCode);
            if (wWorkAreaID > 0) {
                wResult.Result = wResult.Result.stream().filter(p -> p.AreaID == wWorkAreaID)
                        .collect(Collectors.toList());
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<APSTaskStep>> APS_QueryTaskStepByTimeNew(BMSEmployee wLoginUser, Calendar wStartTime,
                                                                       Calendar wEndTime, int wAreaID, int wOrderID) {
        ServiceResult<List<APSTaskStep>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            // 今日时间
            Calendar wTodaySTime = Calendar.getInstance();
            wTodaySTime.set(Calendar.HOUR_OF_DAY, 0);
            wTodaySTime.set(Calendar.MINUTE, 0);
            wTodaySTime.set(Calendar.SECOND, 0);
            Calendar wTodayETime = Calendar.getInstance();
            wTodayETime.set(Calendar.HOUR_OF_DAY, 23);
            wTodayETime.set(Calendar.MINUTE, 59);
            wTodayETime.set(Calendar.SECOND, 59);

            Calendar wBaseTime = Calendar.getInstance();
            wBaseTime.set(2010, 0, 1, 0, 0, 0);
            if (wStartTime.compareTo(wBaseTime) < 0) {
                wStartTime = wTodaySTime;
            }
            if (wEndTime.compareTo(wBaseTime) < 0) {
                wEndTime = wTodayETime;
            }

            wResult.Result = APSTaskStepDAO.getInstance().SelectQueryTaskStep(wLoginUser, wStartTime, wEndTime, wAreaID,
                    wOrderID, wErrorCode);

            List<APSTaskPartDetails> wAPSTaskPartDetailsList = new ArrayList<>();
            List<Integer> wTaskPartIDList = wResult.Result.stream().map(p -> p.TaskPartID).distinct()
                    .collect(Collectors.toList());

            List<APSTaskPart> wTaskPartList = new ArrayList<>();
            if (wTaskPartIDList.size() > 0) {
                wTaskPartList = APSTaskPartDAO.getInstance().SelectListByIDList(wLoginUser, wTaskPartIDList,
                        wErrorCode);
            }

            for (Integer wTaskPartID : wTaskPartIDList) {
                APSTaskPartDetails wAPSTaskPartDetails = new APSTaskPartDetails();
                if (wTaskPartList.stream().anyMatch(p -> p.ID == wTaskPartID)) {
                    wAPSTaskPartDetails.APSTaskPart = wTaskPartList.stream().filter(p -> p.ID == wTaskPartID)
                            .findFirst().get();
                    APSTaskStep wTempStep = wResult.Result.stream().filter(p -> p.TaskPartID == wTaskPartID).findFirst()
                            .get();
                    wAPSTaskPartDetails.AreaID = wTempStep.AreaID;
                    wAPSTaskPartDetails.AreaName = wTempStep.AreaName;
                    wAPSTaskPartDetails.OrderID = wTempStep.OrderID;
                    wAPSTaskPartDetails.OrderNum = wTempStep.OrderNum;
                    wAPSTaskPartDetails.PartID = wTempStep.PartID;
                    wAPSTaskPartDetails.PartNo = wTempStep.PartNo;
                    wAPSTaskPartDetails.ShiftDate = wAPSTaskPartDetails.APSTaskPart.ShiftDate;

                    wAPSTaskPartDetails.StepSize = (int) wResult.Result.stream()
                            .filter(p -> p.TaskPartID == wTaskPartID).count();
                    wAPSTaskPartDetails.StepFinish = (int) wResult.Result.stream()
                            .filter(p -> p.TaskPartID == wTaskPartID && p.Status == 5).count();
                    wAPSTaskPartDetails.StepSchedule = (int) wResult.Result.stream().filter(
                                    p -> p.TaskPartID == wTaskPartID && (p.Status == 2 || p.Status == 4 || p.Status == 5))
                            .count();
                    wAPSTaskPartDetails.StepMaking = (int) wResult.Result.stream().filter(
                                    p -> p.TaskPartID == wTaskPartID && (p.Status == 8 || p.Status == 9 || p.Status == 10))
                            .count();

                    wAPSTaskPartDetailsList.add(wAPSTaskPartDetails);
                }
            }

            List<OMSOrder> wOrderList = new ArrayList<>();
            if (wResult.Result.size() > 0) {
                wOrderList = OMSOrderDAO.getInstance().SelectListByIDList(wLoginUser,
                        wResult.Result.stream().map(p -> p.OrderID).distinct().collect(Collectors.toList()),
                        wErrorCode);
            }

            // 排序
            wAPSTaskPartDetailsList.sort(Comparator.comparing(APSTaskPartDetails::getOrderNum));

            wResult.CustomResult.put("OrderList", wOrderList);
            wResult.CustomResult.put("TaskPartList", wAPSTaskPartDetailsList);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<FMCWorkspace>> APS_QueryPartNoStatusNew(BMSEmployee wLoginUser,
                                                                      List<FMCWorkspace> wList) {
        ServiceResult<List<FMCWorkspace>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            Map<Integer, String> wWorkspaceCarMap = AndonDAO.getInstance().QueryWorkspaceCarMap(wLoginUser, wErrorCode);
            List<Integer> wOrderIDList = new ArrayList<>();
            List<String> wPartNoList = new ArrayList<>();
            for (Integer wSpaceID : wWorkspaceCarMap.keySet()) {
                String wPartNo = wWorkspaceCarMap.get(wSpaceID).replace("[A]", "").replace("[B]", "");
                if (wPartNo.contains("-")) {
                    wPartNo = wPartNo.split("-")[0];
                }
                wPartNoList.add(wPartNo);
            }

            wOrderIDList = OMSOrderDAO.getInstance().SelectIDList(wLoginUser, wPartNoList, wErrorCode);

            if (wOrderIDList.size() > 0) {
                Map<String, Integer> wStatusMap = AndonDAO.getInstance().QueryCarStatusMapNew(wLoginUser,
                        StringUtils.Join(",", wOrderIDList), wErrorCode);
                for (FMCWorkspace wFMCWorkspace : wList) {
                    if (StringUtils.isEmpty(wFMCWorkspace.PartNo)) {
                        continue;
                    }
                    String wPartNo = wFMCWorkspace.PartNo.replace("[A]", "").replace("[B]", "");
                    if (wPartNo.contains("-")) {
                        wPartNo = wPartNo.split("-")[0];
                    }
                    if (wStatusMap.containsKey(wPartNo)) {
                        wFMCWorkspace.Status = wStatusMap.get(wPartNo);
                    }
                }
            }

            wResult.Result = wList;

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public void APS_TriggerDayPlans(BMSEmployee wAdminUser) {
        try {
            if (APSConstans.mAPSSchedulingVersion == null) {
                return;
            }

            // 触发质量日计划
            TriggerQualityDayPlans(wAdminUser, APSConstans.mAPSSchedulingVersion);
            // 制定所有的日计划
            MakingAllTaskStep(wAdminUser, APSConstans.mAPSSchedulingVersion);
            // 置为空
            APSConstans.mAPSSchedulingVersion = null;
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    @Override
    public void APS_TriggerDayPlans(BMSEmployee wAdminUser, APSSchedulingVersion wAPSSchedulingVersion) {
        try {
            // 触发质量日计划
            TriggerQualityDayPlans(wAdminUser, wAPSSchedulingVersion);
            // 制定所有的日计划
            MakingAllTaskStep(wAdminUser, wAPSSchedulingVersion);
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    @Override
    public ServiceResult<List<APSTaskStep>> APS_QueryOrderTimeInfoList(BMSEmployee wLoginUser, int wOrderID,
                                                                       String wStationName) {
        ServiceResult<List<APSTaskStep>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            wResult.Result = APSTaskStepDAO.getInstance().APS_QueryOrderTimeInfoList(wLoginUser, wOrderID, wStationName,
                    wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public void APS_ReMakingDayPlan(BMSEmployee wAdminUser) {
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            int wShiftID = MESServer.MES_QueryShiftID(wAdminUser.CompanyID, Calendar.getInstance(), APSShiftPeriod.Day,
                    FMCShiftLevel.Day, 0);

            SimpleDateFormat wSDF = new SimpleDateFormat("HH");
            int wHour = Integer.parseInt(wSDF.format(Calendar.getInstance().getTime()));

            if (wShiftID != APSConstans.mDayPlanShiftID && wHour >= 1 && wHour <= 2) {
                APSConstans.mDayPlanShiftID = wShiftID;
                // ①将shiftID小于当日的，状态为下达的日计划状态改为保存
                List<APSTaskStep> wList = APSTaskStepDAO.getInstance().SelectListByShiftID(wAdminUser, wShiftID,
                        wErrorCode);
                // ①去除质量日计划
                wList.removeIf(p -> APSConstans.GetFPCPart(p.PartID).PartType == 3
                        || APSConstans.GetFPCPart(p.PartID).PartType == 4);

                for (APSTaskStep wAPSTaskStep : wList) {
                    // ②将这些日计划的派工属性改为0
                    wAPSTaskStep.IsDispatched = false;
                    // ③将这些日计划的派工人员清空
                    wAPSTaskStep.OperatorList = new ArrayList<>();
                    // ④将这些日计划的状态改为保存
                    wAPSTaskStep.Status = APSTaskStatus.Saved.getValue();
                    // ⑤提交数据
                    APSTaskStepDAO.getInstance().Update(wAdminUser, wAPSTaskStep, wErrorCode);
                    // ④将这些日计划的派工任务删除
                    List<SFCTaskStep> wSFCTaskStepList = SFCTaskStepDAO.getInstance().SelectList(wAdminUser, -1,
                            wAPSTaskStep.ID, -1, -1, -1, null, -1, wErrorCode);
                    if (wSFCTaskStepList.size() > 0) {
                        SFCTaskStepDAO.getInstance().DeleteList(wAdminUser, wSFCTaskStepList, wErrorCode);
                    }
                    // ⑤将这些日计划的派工消息删除
                    // SFCTaskStepDAO.getInstance().DeleteMessage(wAdminUser, wSFCTaskStepList,
                    // wErrorCode);
                }
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    @Override

    public ServiceResult<List<APSBOMItem>> APS_QueryBOMItemList(BMSEmployee wLoginUser, int wOrderID, String wWBSNo,
                                                                String wPartNo, int wLineID, int wProductID,
                                                                int wCustomerID, int wPartID, int wPartPointID,
                                                                int wMaterialID, String wMaterialNo, int wBOMType,
                                                                int wReplaceType, int wOutsourceType,
                                                                List<Integer> wStatus, int wDifferenceItem,
                                                                int wOverQuota, int wSourceType) {
        ServiceResult<List<APSBOMItem>> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wErrorCode.set(0);

            wResult.Result = APSBOMItemDAO.getInstance().APS_QueryBOMItemList(wLoginUser, wOrderID, wWBSNo, wPartNo,
                    wLineID, wProductID, wCustomerID, wPartID, wPartPointID, wMaterialID, wMaterialNo, wBOMType,
                    wReplaceType, wOutsourceType, wStatus, wDifferenceItem, wOverQuota, wSourceType, wErrorCode);

            wResult.Result.removeIf(p -> p.DeleteID.equals("X"));

            wResult.FaultCode += MESException.getEnumType(wErrorCode.Result).getLable();

        } catch (Exception e) {

            logger.error(e.toString());

        }

        return wResult;

    }

    @Override

    public ServiceResult<APSBOMItem> APS_QueryBOMItemByID(BMSEmployee wLoginUser, int wID) {

        ServiceResult<APSBOMItem> wResult = new ServiceResult<>();

        try {

            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wErrorCode.set(0);

            wResult.Result = APSBOMItemDAO.getInstance().APS_QueryBOMItemByID(wLoginUser, wID, wErrorCode);

            wResult.FaultCode += MESException.getEnumType(wErrorCode.Result).getLable();

        } catch (Exception e) {

            logger.error(e.toString());

        }

        return wResult;

    }

    @Override

    public ServiceResult<String> APS_UpdateBOMItem(BMSEmployee wLoginUser, APSBOMItem wBOMItem) {
        ServiceResult<String> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wErrorCode.set(0);

            // 判断是否为差异项
            wBOMItem.DifferenceItem = APSBOMItemDAO.getInstance().JudgeIsDifferenceItem(wLoginUser, wBOMItem,
                    wErrorCode);

            // 修改评估类型
            if (wBOMItem.SourceType != APSBOMSourceType.SFCBOMTask.getValue()
                    && wBOMItem.SourceType != APSBOMSourceType.BOMAudit.getValue()) {
                if (wBOMItem.ReplaceType == 1) {
                    wBOMItem.AssessmentType = "常规新件";
                } else if (wBOMItem.OutsourceType == 1 || wBOMItem.OutsourceType == 2) {
                    wBOMItem.AssessmentType = "修复旧件";
                } else if (wBOMItem.PartChange > 0) {
                    wBOMItem.AssessmentType = "修复旧件";
                } else if (wBOMItem.OutsourceType == 3 || wBOMItem.OutsourceType == 4) {
                    wBOMItem.AssessmentType = "可用旧件";
                }
            }

            // 如果来源于标准BOM变更，如果是必换件或委外必修件 ，判断MES系统中是否存在相同的物料，存在，直接返回
            if (wBOMItem.SourceType == APSBOMSourceType.BOMChange.getValue()) {
                if (wBOMItem.ReplaceType == 1 || wBOMItem.OutsourceType == 1) {
                    List<APSBOMItem> wExsitList = APSBOMItemDAO.getInstance().APS_QueryBOMItemList(wLoginUser,
                            wBOMItem.OrderID, "", "", -1, -1, -1, wBOMItem.PartID, wBOMItem.PartPointID,
                            wBOMItem.MaterialID, "", -1, wBOMItem.ReplaceType, wBOMItem.OutsourceType, null, -1, -1, -1,
                            wErrorCode);
                    wExsitList.removeIf(p -> p.DeleteID.equals("X"));
                    if (wExsitList.size() > 0) {
                        // 判断是否需要重推，如果失败的话
                        if (wExsitList.get(0).SAPStatus == 2 || wExsitList.get(0).SAPStatus == 0) {
                            wResult.Result = APSServiceImpl.getInstance().APS_ReSendBOMByIDList(wLoginUser,
                                    new ArrayList<>(Collections.singletonList(wExsitList.get(0).ID))).Result;
                        }
                        return wResult;
                    }
                }
            }

            // 如果来源为台车bom变更，则判断是否存在相同的，来源为台车bom变更的物料（失败重推）
            if (wBOMItem.SourceType == APSBOMSourceType.BOMAudit.getValue()) {
                if (wBOMItem.ReplaceType == 1 || wBOMItem.OutsourceType == 1) {
                    List<APSBOMItem> wExsitList = APSBOMItemDAO.getInstance().APS_QueryBOMItemList(wLoginUser,
                            wBOMItem.OrderID, "", "", -1, -1, -1, wBOMItem.PartID, wBOMItem.PartPointID,
                            wBOMItem.MaterialID, "", -1, wBOMItem.ReplaceType, wBOMItem.OutsourceType, null, -1, -1,
                            APSBOMSourceType.BOMAudit.getValue(),
                            wErrorCode);
                    wExsitList.removeIf(p -> p.DeleteID.equals("X"));
                    if (wExsitList.size() > 0) {
                        // 判断是否需要重推，如果失败的话
                        if (wExsitList.get(0).SAPStatus == 2 || wExsitList.get(0).SAPStatus == 0) {
                            wResult.Result = APSServiceImpl.getInstance().APS_ReSendBOMByIDList(wLoginUser,
                                    new ArrayList<>(Collections.singletonList(wExsitList.get(0).ID))).Result;
                        } else {
                            wResult.Result = StringUtils.Format("推送失败：物料{0}已提台车变更", wBOMItem.MaterialNo);
                        }
                        wBOMItem.ID = wExsitList.get(0).ID;
                        wBOMItem.OrderNum = wExsitList.get(0).OrderNum;
                        wBOMItem.SourceID = wExsitList.get(0).SourceID;
                        return wResult;
                    }
                }
            }

            OMSOrder wOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wBOMItem.OrderID, wErrorCode);

            List<APSBOMItem> wList = new ArrayList<>(Collections.singletonList(wBOMItem));

            // 验证台车BOM
            String wMsg = APSBOMUtils.getInstance().CheckAPSBOM(wList, wOrder);

            if (StringUtils.isNotEmpty(wMsg)) {

                List<BFCMessage> wBFCMessageList = new ArrayList<>();
                BFCMessage wMessage = null;
                int wShiftID = MESServer.MES_QueryShiftID(wLoginUser.CompanyID, Calendar.getInstance(),
                        APSShiftPeriod.Day, FMCShiftLevel.Day, 0);
                // 发送任务消息到人员
                wMessage = new BFCMessage();
                wMessage.Active = 0;
                wMessage.CompanyID = 0;
                wMessage.CreateTime = Calendar.getInstance();
                wMessage.EditTime = Calendar.getInstance();
                wMessage.ID = 0;
                wMessage.MessageID = 0;
                wMessage.Title = StringUtils.Format("【台车BOM】提示", BPMEventModule.StationTip.getLable());
                wMessage.MessageText = wMsg;
                wMessage.ModuleID = BPMEventModule.StationTip.getValue();
                wMessage.ResponsorID = StringUtils.parseInt(Configuration.readConfigString("bomUser", "config/config"));
                wMessage.ShiftID = wShiftID;
                wMessage.StationID = 0;
                wMessage.Type = BFCMessageType.Notify.getValue();
                wBFCMessageList.add(wMessage);

                CoreServiceImpl.getInstance().BFC_UpdateMessageList(wLoginUser, wBFCMessageList);

                // 返回提示信息
                wResult.Result = wMsg;
                wResult.FaultCode = wMsg;
                return wResult;
            }

            wBOMItem.ID = APSBOMItemDAO.getInstance().APS_UpdateBOMItem(wLoginUser, wBOMItem, wErrorCode);

            wBOMItem = APSBOMItemDAO.getInstance().APS_QueryBOMItemByID(wLoginUser, wBOMItem.ID, wErrorCode);

            wList = new ArrayList<>(Collections.singletonList(wBOMItem));

            String wSendSAP = Configuration.readConfigString("isSendSAP", "config/config");

            if (wSendSAP.equals("1")) {
                // ①推送台车BOM给SAP
                String wJson = APSBOMUtils.getInstance().ChangeToJson(wList, "U");
                List<Integer> wAPSBOMIDList = wList.stream().map(p -> p.ID).distinct().collect(Collectors.toList());
                if (StringUtils.isNotEmpty(wJson)) {
                    wResult.Result = SendToSAP(wLoginUser, wJson, wOrder.OrderNo, 0, wOrder, 0, wAPSBOMIDList, 2);
                }
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(e.toString());
        }
        return wResult;
    }


    @Override

    public ServiceResult<String> APS_UpdateBOMItem(BMSEmployee wLoginUser, List<APSBOMItem> wBOMItemList) {
        ServiceResult<String> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wErrorCode.set(0);

            //获取标准BOM中对应物料信息清单

            Map<Integer, List<APSBOMItem>> collect = wBOMItemList.stream().collect(Collectors.groupingBy(p -> p.OrderID));


            for (Integer wOrderID : collect.keySet()) {

                wResult = this.APS_UpdateBOMItem(wLoginUser, wOrderID, collect.get(wOrderID));
                if (StringUtils.isNotEmpty(wResult.Result)) {
                    return wResult;
                }
            }

        } catch (Exception e) {
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override

    public ServiceResult<String> APS_UpdateBOMItem(BMSEmployee wLoginUser, int wOrderID, List<APSBOMItem> wBOMItemList) {
        ServiceResult<String> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wErrorCode.set(0);
            OMSOrder wOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wOrderID, wErrorCode);
            if (wErrorCode.Result != 0) {
                wResult.FaultCode += MESException.getEnumType(wErrorCode.Result).getLable();

                wBOMItemList.forEach(p -> p.ErrorCode = "台车订单 查询错误：" + wResult.FaultCode);
                return wResult;
            }
            //获取标准BOM中对应物料信息清单
            List<Integer> wBOMIDList = MSSBOMItemDAO.getInstance().QueryBOMID(wLoginUser, wOrderID, wErrorCode);
            if (wErrorCode.Result != 0) {
                wResult.FaultCode += MESException.getEnumType(wErrorCode.Result).getLable();
                wBOMItemList.forEach(p -> p.ErrorCode = "标准BOMID 查询错误：" + wResult.FaultCode);
                return wResult;
            }

            List<MSSBOMItem> wMSSBOMItemList = MSSBOMItemDAO.getInstance().SelectList(wLoginUser, wBOMIDList, wErrorCode);
            if (wErrorCode.Result != 0) {
                wResult.FaultCode += MESException.getEnumType(wErrorCode.Result).getLable();
                wBOMItemList.forEach(p -> p.ErrorCode = "标准BOM 查询错误：" + wResult.FaultCode);
                return wResult;
            }
            List<APSBOMItem> wAPSBOMItemList = APSBOMItemDAO.getInstance().APS_QueryBOMItemList(wLoginUser,
                    wOrderID, "", "", -1, -1, -1, -1, -1,
                    -1, "", -1, -1, -1, null, -1, -1, -1,
                    wErrorCode);

            if (wErrorCode.Result != 0) {
                wResult.FaultCode += MESException.getEnumType(wErrorCode.Result).getLable();
                wBOMItemList.forEach(p -> p.ErrorCode = "台车BOM 查询错误：" + wResult.FaultCode);
                return wResult;
            }
            wAPSBOMItemList.removeIf(p -> p.DeleteID.equals("X"));

            List<APSBOMItem> wExsitList;

            List<Integer> wReSendID = new ArrayList<>();
            List<APSBOMItem> wList = new ArrayList<>();
            for (APSBOMItem wBOMItem : wBOMItemList) {

                // 判断是否为差异项
                wBOMItem.DifferenceItem = 0;
                if (!wMSSBOMItemList.stream().anyMatch(p -> p.PlaceID == wBOMItem.PartID && p.PartPointID == wBOMItem.PartPointID
                        && p.MaterialID == wBOMItem.MaterialID)) {
                    wBOMItem.DifferenceItem = 1;
                }

                // 修改评估类型
                if (wBOMItem.SourceType != APSBOMSourceType.SFCBOMTask.getValue()
                        && wBOMItem.SourceType != APSBOMSourceType.BOMAudit.getValue()) {
                    if (wBOMItem.ReplaceType == 1) {
                        wBOMItem.AssessmentType = "常规新件";
                    } else if (wBOMItem.OutsourceType == 1 || wBOMItem.OutsourceType == 2) {
                        wBOMItem.AssessmentType = "修复旧件";
                    } else if (wBOMItem.PartChange > 0) {
                        wBOMItem.AssessmentType = "修复旧件";
                    } else if (wBOMItem.OutsourceType == 3 || wBOMItem.OutsourceType == 4) {
                        wBOMItem.AssessmentType = "可用旧件";
                    }
                }

                // 如果来源于标准BOM变更，如果是必换件或委外必修件 ，判断MES系统中是否存在相同的物料，存在，直接返回
                if (wBOMItem.SourceType == APSBOMSourceType.BOMChange.getValue()) {
                    if (wBOMItem.ReplaceType == 1 || wBOMItem.OutsourceType == 1) {
                        wExsitList = wAPSBOMItemList.stream().filter(p -> p.PartID == wBOMItem.PartID
                                && p.PartPointID == wBOMItem.PartPointID && p.MaterialID == wBOMItem.MaterialID
                                && p.ReplaceType == wBOMItem.ReplaceType && p.OutsourceType == wBOMItem.OutsourceType).collect(Collectors.toList());

                        if (wExsitList.size() > 0) {
                            // 判断是否需要重推，如果失败的话
                            if (wExsitList.get(0).SAPStatus == 2 || wExsitList.get(0).SAPStatus == 0) {

                                wReSendID.add(wExsitList.get(0).ID);
                            } else {
                                wBOMItem.ErrorCode += StringUtils.Format("推送失败：物料{0}已提台车变更", wBOMItem.MaterialNo);
                            }
                            continue;
                        }
                    }
                }

                // 如果来源为台车bom变更，则判断是否存在相同的，来源为台车bom变更的物料（失败重推）
                if (wBOMItem.SourceType == APSBOMSourceType.BOMAudit.getValue()) {
                    if (wBOMItem.ReplaceType == 1 || wBOMItem.OutsourceType == 1) {

                        wExsitList = wAPSBOMItemList.stream().filter(p -> p.PartID == wBOMItem.PartID
                                && p.PartPointID == wBOMItem.PartPointID && p.MaterialID == wBOMItem.MaterialID
                                && p.ReplaceType == wBOMItem.ReplaceType && p.OutsourceType == wBOMItem.OutsourceType
                                && p.SourceType == APSBOMSourceType.BOMAudit.getValue()).collect(Collectors.toList());


                        if (wExsitList.size() > 0) {
                            // 判断是否需要重推，如果失败的话
                            if (wExsitList.get(0).SAPStatus == 2 || wExsitList.get(0).SAPStatus == 0) {
                                wReSendID.add(wExsitList.get(0).ID);
                            } else {
                                wBOMItem.ErrorCode += StringUtils.Format("推送失败：物料{0}已提台车变更", wBOMItem.MaterialNo);
                            }
                            wBOMItem.ID = wExsitList.get(0).ID;
                            wBOMItem.OrderNum = wExsitList.get(0).OrderNum;
                            wBOMItem.SourceID = wExsitList.get(0).SourceID;
                            continue;
                        }
                    }
                }
                wList.add(wBOMItem);
            }

            if (wReSendID.size() > 0) {
                wResult.Result += APSServiceImpl.getInstance().APS_ReSendBOMByIDList(wLoginUser,
                        wReSendID).Result;

                wBOMItemList.forEach(p -> {
                    if (wReSendID.contains(p.ID)) p.ErrorCode += wResult.FaultCode;
                });
            }


            // 验证台车BOM
            String wMsg = APSBOMUtils.getInstance().CheckAPSBOM(wBOMItemList, wOrder);

            if (StringUtils.isNotEmpty(wMsg)) {

                List<BFCMessage> wBFCMessageList = new ArrayList<>();
                BFCMessage wMessage = null;
                int wShiftID = MESServer.MES_QueryShiftID(wLoginUser.CompanyID, Calendar.getInstance(),
                        APSShiftPeriod.Day, FMCShiftLevel.Day, 0);
                // 发送任务消息到人员
                wMessage = new BFCMessage();
                wMessage.Active = 0;
                wMessage.CompanyID = 0;
                wMessage.CreateTime = Calendar.getInstance();
                wMessage.EditTime = Calendar.getInstance();
                wMessage.ID = 0;
                wMessage.MessageID = 0;
                wMessage.Title = StringUtils.Format("【台车BOM】提示", BPMEventModule.StationTip.getLable());
                wMessage.MessageText = wMsg;
                wMessage.ModuleID = BPMEventModule.StationTip.getValue();
                wMessage.ResponsorID = StringUtils.parseInt(Configuration.readConfigString("bomUser", "config/config"));
                wMessage.ShiftID = wShiftID;
                wMessage.StationID = 0;
                wMessage.Type = BFCMessageType.Notify.getValue();
                wBFCMessageList.add(wMessage);

                CoreServiceImpl.getInstance().BFC_UpdateMessageList(wLoginUser, wBFCMessageList);

                // 返回提示信息
                wResult.Result = wMsg;
                wResult.FaultCode = wMsg;

                wBOMItemList.forEach(p -> p.ErrorCode += wResult.FaultCode);

                return wResult;
            }
            String wSendSAP = Configuration.readConfigString("isSendSAP", "config/config");
            if (!wSendSAP.equals("1")) {
                logger.info("推送台车BOM给SAP已关闭");
                return wResult;
            }

            for (APSBOMItem wBOMItem : wList) {
                wBOMItem.ID = APSBOMItemDAO.getInstance().APS_UpdateBOMItem(wLoginUser, wBOMItem, wErrorCode);
                wBOMItem.ErrorCode += MESException.getEnumType(wErrorCode.Result).getLable();
            }
            List<APSBOMItem> wNewList=APSBOMItemDAO.getInstance().SelectByIDList(wLoginUser, wList.stream().map(p -> p.ID).collect(Collectors.toList()),wErrorCode);

            if(wErrorCode.Result!=0){
                wList.forEach(p -> p.ErrorCode += wResult.FaultCode);
                wResult.FaultCode+=MESException.getEnumType(wErrorCode.Result).getLable();
            }

            if ( wNewList.size() > 0) {
                // ①推送台车BOM给SAP
                String wJson = APSBOMUtils.getInstance().ChangeToJson(wNewList, "U");
                List<Integer> wAPSBOMIDList = wNewList.stream().map(p -> p.ID).distinct().collect(Collectors.toList());
                if (StringUtils.isNotEmpty(wJson)) {
                    wResult.Result = SendToSAP(wLoginUser, wJson, wOrder.OrderNo, 0, wOrder, 0, wAPSBOMIDList, 2);

                    wList.forEach(p -> p.ErrorCode += wResult.FaultCode);
                }
            }

        } catch (Exception e) {
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<APSBOMItem>> APS_CreateBOMItem(BMSEmployee wLoginUser, int wRouteID,
                                                             List<APSBOMItem> wBOMItemList) {
        ServiceResult<List<APSBOMItem>> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            if (wBOMItemList == null || wBOMItemList.size() <= 0) {
                return wResult;
            }

            APSBOMItem wAPSBOMItem = wBOMItemList.get(0);

            List<MSSBOMItem> wMSSBOMItemList = WMSServiceImpl.getInstance().MSS_QueryBOMItemAll(wLoginUser, -1,
                            wAPSBOMItem.LineID, wAPSBOMItem.ProductID, wAPSBOMItem.CustomerID, -1, -1, -1, -1, wRouteID)
                    .List(MSSBOMItem.class);

            List<APSBOMItem> wResultList = new ArrayList<>();

            APSBOMItem wBOMItem = null;

            for (MSSBOMItem wMSSBOMItem : wMSSBOMItemList) {

                if (wMSSBOMItem.Active != 1)
                    continue;

                if (wMSSBOMItem.ReplaceType == 1 || wMSSBOMItem.OutsourceType == 1) {

                    wBOMItem = new APSBOMItem(wMSSBOMItem, wAPSBOMItem.LineID, wAPSBOMItem.ProductID,
                            wAPSBOMItem.CustomerID, wAPSBOMItem.OrderID, wAPSBOMItem.WBSNo, wAPSBOMItem.PartNo);

                    wBOMItem.SourceType = APSBOMSourceType.StandardBOM.getValue();
                    wBOMItem.SourceID = wMSSBOMItem.ID;

                    wResultList.add(wBOMItem);
                }
            }

            wResultList.addAll(wBOMItemList);

            APSBOMItemDAO.getInstance().APS_CreateBOMItem(wLoginUser, wResultList, wErrorCode);

            wResult.Result = APSBOMItemDAO.getInstance().APS_QueryBOMItemList(wLoginUser, wAPSBOMItem.getOrderID(),

                    wAPSBOMItem.getWBSNo(), wAPSBOMItem.getPartNo(), wAPSBOMItem.getLineID(),

                    wAPSBOMItem.getProductID(), wAPSBOMItem.getCustomerID(), 0, 0, 0, "", 0, 0, 0, null, -1, -1, -1,
                    wErrorCode);

            wResult.FaultCode += MESException.getEnumType(wErrorCode.Result).getLable();

        } catch (Exception e) {
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<APSBOMItem>> APS_CreateBOMItem(BMSEmployee wLoginUser, int wRouteID, int wLineID,
                                                             int wProductID, int wCustomerID, int wOrderID,
                                                             String wWBSNo, String wPartNo) {
        ServiceResult<List<APSBOMItem>> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            List<MSSBOMItem> wMSSBOMItemList = WMSServiceImpl.getInstance()
                    .MSS_QueryBOMItemAll(wLoginUser, -1, wLineID, wProductID, wCustomerID, -1, -1, -1, -1, wRouteID)
                    .List(MSSBOMItem.class);

            List<APSBOMItem> wResultList = new ArrayList<>();

            APSBOMItem wBOMItem = null;

            for (MSSBOMItem wMSSBOMItem : wMSSBOMItemList) {
                if (wMSSBOMItem.Active != 1)
                    continue;

                if (wMSSBOMItem.ReplaceType == 1 || wMSSBOMItem.OutsourceType == 1) {
                    wBOMItem = new APSBOMItem(wMSSBOMItem, wLineID, wProductID, wCustomerID, wOrderID, wWBSNo, wPartNo);

                    wBOMItem.SourceType = APSBOMSourceType.StandardBOM.getValue();
                    wBOMItem.SourceID = wMSSBOMItem.ID;

                    wResultList.add(wBOMItem);
                }
            }

            APSBOMItemDAO.getInstance().APS_CreateBOMItem(wLoginUser, wResultList, wErrorCode);

            wResult.Result = APSBOMItemDAO.getInstance().APS_QueryBOMItemList(wLoginUser, wOrderID, wWBSNo, wPartNo,
                    wLineID, wProductID, wCustomerID, 0, 0, 0, "", 0, 0, 0, null, -1, -1, -1, wErrorCode);

            wResult.FaultCode += MESException.getEnumType(wErrorCode.Result).getLable();
        } catch (Exception e) {
            logger.error(e.toString());
        }

        return wResult;
    }

    @Override
    public ServiceResult<String> APS_DeleteBOMItem(BMSEmployee wLoginUser, APSBOMItem wBOMItem) {
        ServiceResult<String> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            // 根据订单ID，工位、工序、物料ID 查询物料
            APSBOMItem wItem = null;
            if (wBOMItem.ID > 0) {
                wItem = wBOMItem;
            } else {
                wItem = APSBOMItemDAO.getInstance().APS_SelectItem(wLoginUser, wBOMItem.OrderID, wBOMItem.PartID,
                        wBOMItem.PartPointID, wBOMItem.MaterialID, wBOMItem.ReplaceType, wBOMItem.OutsourceType,
                        wErrorCode);
            }

            if (wItem != null && wItem.ID > 0) {
                // 标准bom删除
                wItem.DeleteID = "X";
                wItem.QTType = wBOMItem.QTType;
                int wNewID = APSBOMItemDAO.getInstance().APS_UpdateBOMItem(wLoginUser, wItem, wErrorCode);

                // 推送给SAP(更新)
                if (wBOMItem.OrderID > 0) {
                    wResult.Result = APSServiceImpl.getInstance().APS_UpdateBomItemByBOMItem(BaseDAO.SysAdmin,
                            wNewID).Result;
                }
            }

            wResult.FaultCode += MESException.getEnumType(wErrorCode.Result).getLable();
        } catch (Exception e) {
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> APS_CreateBomItemByOrder(BMSEmployee wLoginUser, int wOrderID) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            OMSOrder wOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wOrderID, wErrorCode);

            int wBOMID = APSBOMItemDAO.getInstance().GetCurrentStandardBOMID(wLoginUser, wOrder.ProductID,
                    wOrder.LineID, wOrder.CustomerID, wOrder.RouteID, wErrorCode);

            if (wOrder.RouteID <= 0) {
                wBOMID = 0;
            }

            wOrder.BOMID = wBOMID;

            List<MSSBOMItem> wMSSBOMItemList = null;
            if (wBOMID > 0) {
                wMSSBOMItemList = WMSServiceImpl.getInstance()
                        .MSS_QueryBOMItemAll(wLoginUser, wBOMID, -1, -1, -1, -1, -1, -1, -1, -1).List(MSSBOMItem.class);
            }

            if (wMSSBOMItemList == null || wMSSBOMItemList.size() <= 0) {

                // 返回提示信息
                wResult.FaultCode = StringUtils.Format("提示：【{0}】该车辆无当前标准BOM，创建台车BOM失败!", wOrder.PartNo);

                // 发送创建台车bom的消息
                SendAPSBOMMessageAddBOMID(wLoginUser, wResult.FaultCode, wBOMID, wOrder);

                return wResult;
            }

            List<APSBOMItem> wResultList = new ArrayList<>();

            APSBOMItem wBOMItem = null;

            String wNotPartIDs = Configuration.readConfigString("NoPickDemandPartIDs", "config/config");
            List<Integer> wNotPartIDList = StringUtils.parseIntList(wNotPartIDs.split(","));

            for (MSSBOMItem wMSSBOMItem : wMSSBOMItemList) {

                if (wMSSBOMItem.Active == 2)
                    continue;

                if (wNotPartIDList.stream().anyMatch(p -> p == wMSSBOMItem.PlaceID)) {
                    continue;
                }

                // 此处需要过滤预检、拆解等配置的工位bom（待开发）

                if (wMSSBOMItem.ReplaceType == 1 || wMSSBOMItem.OutsourceType == 1) {

                    wBOMItem = new APSBOMItem(wMSSBOMItem, wOrder.LineID, wOrder.ProductID, wOrder.CustomerID,
                            wOrder.ID, wOrder.OrderNo, wOrder.PartNo);

                    wBOMItem.SourceType = APSBOMSourceType.StandardBOM.getValue();
                    wBOMItem.SourceID = wMSSBOMItem.ID;
                    wBOMItem.AuditorID = wLoginUser.ID;
                    wBOMItem.EditorID = wLoginUser.ID;
                    wBOMItem.AuditTime = Calendar.getInstance();
                    wBOMItem.EditTime = Calendar.getInstance();

                    wResultList.add(wBOMItem);
                }
            }

            // 验证台车BOM
            String wMsg = APSBOMUtils.getInstance().CheckAPSBOM(wResultList, wOrder);
            if (StringUtils.isNotEmpty(wMsg)) {

                // 发送创建台车bom的消息
                SendAPSBOMMessageAddBOMID(wLoginUser, wMsg, wBOMID, wOrder);

                // 返回提示信息
                wResult.FaultCode = wMsg;
                return wResult;
            }

            // 重新编号
            int wFlag = 1;
            for (APSBOMItem wAPSBOMItem : wResultList) {
                wAPSBOMItem.OrderNum = wFlag++;
            }

            // 评估类型赋值
            wResultList.forEach(p -> {
                if (p.OutsourceType == 1) {
                    p.AssessmentType = "修复旧件";
                }
                if (p.ReplaceType == 1 && p.OutsourceType == 1) {
                    p.AssessmentType = "常规新件";
                }
            });

            APSBOMItemDAO.getInstance().APS_CreateBOMItem(wLoginUser, wResultList, wErrorCode);

            List<APSBOMItem> wList = APSBOMItemDAO.getInstance().APS_QueryBOMItemList(wLoginUser, wOrderID, "", "", -1,
                    -1, -1, -1, -1, -1, "", -1, -1, -1, null, -1, -1, -1, wErrorCode);

            String wSendSAP = Configuration.readConfigString("isSendSAP", "config/config");
            if (wSendSAP.equals("1")) {
                // ①推送台车BOM给SAP
                String wJson = APSBOMUtils.getInstance().ChangeToJson(wList, "I");
                if (StringUtils.isNotEmpty(wJson)) {
                    SendToSAP(wLoginUser, wJson, wOrder.OrderNo, 0, wOrder, 1,
                            wList.stream().map(p -> p.ID).collect(Collectors.toList()), 1);
                }
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }


    private void SendAPSBOMMessageAddBOMID(BMSEmployee wLoginUser, String wMsg, int wBOMID, OMSOrder wOrder) {
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            int wStatus = 0;
            if (wMsg.contains("失败") || wMsg.contains("E")) {
                wStatus = 2;
            } else if (wMsg.contains("成功")) {
                wStatus = 1;

                List<APSBOMLog> wHisList = APSBOMLogDAO.getInstance().SelectList(wLoginUser, -1, -1, -1, -1, wOrder.ID,
                        2, null, null, wErrorCode);
                for (APSBOMLog wAPSBOMLog : wHisList) {
                    wAPSBOMLog.Status = 3;
                    APSBOMLogDAO.getInstance().Update(wLoginUser, wAPSBOMLog, wErrorCode);
                }
            }

            APSBOMLog wLog = new APSBOMLog(0, wOrder.ProductID, wOrder.ProductNo, wOrder.LineID, wOrder.LineName,
                    wOrder.CustomerID, wOrder.Customer, wOrder.ID, wOrder.PartNo, wOrder.OrderNo, wStatus, wMsg,
                    Calendar.getInstance());
            wLog.BOMID = wBOMID;
            int wMessageID = APSBOMLogDAO.getInstance().Update(wLoginUser, wLog, wErrorCode);

            // 此处推送消息，告知为何创建台车bom失败
            List<BFCMessage> wBFCMessageList = new ArrayList<>();
            BFCMessage wMessage = null;
            int wShiftID = MESServer.MES_QueryShiftID(wLoginUser.CompanyID, Calendar.getInstance(), APSShiftPeriod.Day,
                    FMCShiftLevel.Day, 0);

            String wBomUser = Configuration.readConfigString("bomUser", "config/config");
            String[] wUserList = wBomUser.split(",");
            for (String wUserIDStr : wUserList) {
                int wUserID = StringUtils.parseInt(wUserIDStr);

                // 发送任务消息到人员
                wMessage = new BFCMessage();
                wMessage.Active = 0;
                wMessage.CompanyID = 0;
                wMessage.CreateTime = Calendar.getInstance();
                wMessage.EditTime = Calendar.getInstance();
                wMessage.ID = 0;
                wMessage.MessageID = 0;
                wMessage.Title = StringUtils.Format("{0} {1}", BPMEventModule.APSBOMCreateNotify.getLable(), wShiftID);

                if (wStatus == 1) {
                    wMessage.MessageText = StringUtils.Format("【{0}】{1}", wOrder.PartNo, wMsg);
                } else if (wStatus == 2) {
                    wMessage.MessageText = StringUtils.Format("【{0}】创建台车BOM失败，请查看失败详情，并及时处理。", wOrder.PartNo);
                } else {
                    wMessage.MessageText = StringUtils.Format("【{0}】{1}", wOrder.PartNo, wMsg);
                }

                wMessage.ModuleID = BPMEventModule.APSBOMCreateNotify.getValue();
                wMessage.MessageID = wMessageID;
                wMessage.ResponsorID = wUserID;
                wMessage.ShiftID = wShiftID;
                wMessage.StationID = 0;
                wMessage.Type = BFCMessageType.Notify.getValue();
                wBFCMessageList.add(wMessage);
            }

            CoreServiceImpl.getInstance().BFC_UpdateMessageList(wLoginUser, wBFCMessageList);
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    @Override
    public ServiceResult<String> APS_UpdateBomItemByBOMItem(BMSEmployee wLoginUser, int wBomItemID) {
        ServiceResult<String> wResult = new ServiceResult<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            APSBOMItem wItem = APSBOMItemDAO.getInstance().APS_QueryBOMItemByID(wLoginUser, wBomItemID, wErrorCode);

            if (wItem == null || wItem.ID <= 0) {
                return wResult;
            }

            OMSOrder wOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wItem.OrderID, wErrorCode);

            List<APSBOMItem> wList = new ArrayList<>(Collections.singletonList(wItem));

            // 验证台车BOM
            String wMsg = APSBOMUtils.getInstance().CheckAPSBOM(wList, wOrder);

            if (StringUtils.isNotEmpty(wMsg)) {

                List<BFCMessage> wBFCMessageList = new ArrayList<>();
                BFCMessage wMessage = null;
                int wShiftID = MESServer.MES_QueryShiftID(wLoginUser.CompanyID, Calendar.getInstance(),
                        APSShiftPeriod.Day, FMCShiftLevel.Day, 0);
                // 发送任务消息到人员
                wMessage = new BFCMessage();
                wMessage.Active = 0;
                wMessage.CompanyID = 0;
                wMessage.CreateTime = Calendar.getInstance();
                wMessage.EditTime = Calendar.getInstance();
                wMessage.ID = 0;
                wMessage.MessageID = 0;
                wMessage.Title = StringUtils.Format("【台车BOM】提示", BPMEventModule.StationTip.getLable());
                wMessage.MessageText = wMsg;
                wMessage.ModuleID = BPMEventModule.StationTip.getValue();
                wMessage.ResponsorID = StringUtils.parseInt(Configuration.readConfigString("bomUser", "config/config"));
                wMessage.ShiftID = wShiftID;
                wMessage.StationID = 0;
                wMessage.Type = BFCMessageType.Notify.getValue();
                wBFCMessageList.add(wMessage);

                CoreServiceImpl.getInstance().BFC_UpdateMessageList(wLoginUser, wBFCMessageList);

                // 返回提示信息
                wResult.FaultCode = wMsg;
                return wResult;
            }

            String wSendSAP = Configuration.readConfigString("isSendSAP", "config/config");

            if (wSendSAP.equals("1")) {
                // ①推送台车BOM给SAP
                String wJson = APSBOMUtils.getInstance().ChangeToJson(wList, "U");
                List<Integer> wAPSBOMIDList = wList.stream().map(p -> p.ID).distinct().collect(Collectors.toList());
                if (StringUtils.isNotEmpty(wJson)) {
                    wResult.Result = SendToSAP(wLoginUser, wJson, wOrder.OrderNo, 0, wOrder, 0, wAPSBOMIDList, 2);
                }
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    /**
     * 将台车BOM发送给SAP
     * wUpdateType ：台车BOM更新类型 1：新增 2：修改
     */
    private String SendToSAP(BMSEmployee wLoginUser, String wJson, String wWBSNo, int wSFCBOMTaskID, OMSOrder wOrder,
                             int wMode, List<Integer> wAPSBOMIDList, int wUpdateType) {
        String wResult = "";
        try {
            String wEndPoint = APSUtils.getInstance().GetSAPEndpoint();
            if (wUpdateType > 0) {
                wEndPoint = APSUtils.getInstance().GetSAPEndpoint(wUpdateType);
            }

            org.apache.axis.client.Service wService = new org.apache.axis.client.Service();
            Call wCall = (Call) wService.createCall();

            wCall.setUsername(APSUtils.getInstance().GetSAPUser());
            wCall.setPassword(APSUtils.getInstance().GetSAPPassword());

            wCall.setTargetEndpointAddress(wEndPoint);
            wCall.setOperationName(new QName("urn:sap-com:document:sap:rfc:functions", "ZIF_MES_INPUT_001"));// 调用的方法名
            wCall.addParameter("INPUT1", XMLType.XSD_STRING, javax.xml.rpc.ParameterMode.IN);
            wCall.addParameter("INPUT2", XMLType.XSD_STRING, javax.xml.rpc.ParameterMode.IN);
            wCall.setReturnType(XMLType.XSD_STRING); // 返回值类型：String

            String wReturn = (String) wCall.invoke(new Object[]{"01", wJson});// 远程调用

            // 处理重复的文本提示
            wReturn = APSBOMItemDAO.getInstance().HandleRepeatText(wReturn);

            logger.info(wWBSNo + "::" + wReturn);

            CalendarDAO.getInstance().WriteLogFile(wJson + "::" + wReturn, "台车bom", wOrder, "");

            wResult = wReturn;

            String wErrorMsg = wReturn;

            if (wSFCBOMTaskID > 0 && wMode == 0) {
                ExecutorService wES = Executors.newFixedThreadPool(1);
                wES.submit(() -> UpdateSFCBOMTaskSAPStatus(wLoginUser, wErrorMsg, wSFCBOMTaskID));
                wES.shutdown();
            } else if (wSFCBOMTaskID > 0 && wMode == 2) {
                ExecutorService wES = Executors.newFixedThreadPool(1);
                wES.submit(() -> UpdateSFCScrapApprovalBPMSAPStatus(wLoginUser, wErrorMsg, wSFCBOMTaskID));
                wES.shutdown();
            }

            if (wMode == 1) {
                // 发送创建台车bom的消息
                APSBOMUtils.getInstance().SendAPSBOMMessage(wLoginUser, wResult, wOrder);
            }

            if (wAPSBOMIDList != null && wAPSBOMIDList.size() > 0) {
                String wMsg = wResult;
                TaskTimerUtils.AddTask("UpdateAPSBOMMsg", () -> {
                    APSBOMUtils.getInstance().UpdateAPSBOMMsg(wLoginUser, wAPSBOMIDList, wMsg);
                }, 1000);

            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
        return wResult;
    }


    @Override
    public ServiceResult<List<OMSOrder>> APS_QueryOrderBOMList(BMSEmployee wLoginUser, List<Integer> wCustomerList,
                                                               List<Integer> wLineList, List<Integer> wStatusList,
                                                               List<Integer> wProductList, String wPartNo,
                                                               List<Integer> wActiveList, Calendar wStartTime,
                                                               Calendar wEndTime) {
        ServiceResult<List<OMSOrder>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            boolean wIsAll = wStatusList.stream().anyMatch(p -> p == -1);

            if (wCustomerList != null && wCustomerList.size() > 0) {
                wCustomerList.removeIf(p -> p == -1);
            }
            if (wLineList != null && wLineList.size() > 0) {
                wLineList.removeIf(p -> p == -1);
            }
            if (wStatusList.size() > 0) {
                wStatusList.removeIf(p -> p == -1);
            }
            if (wProductList != null && wProductList.size() > 0) {
                wProductList.removeIf(p -> p == -1);
            }
            if (wActiveList != null && wActiveList.size() > 0) {
                wActiveList.removeIf(p -> p == -1);
            }

            List<OMSOrder> wList = OMSOrderDAO.getInstance().SelectList(wLoginUser, wCustomerList, wLineList,
                    wStartTime, wEndTime, wStatusList, wProductList, wPartNo, wActiveList, wErrorCode);

            if (wIsAll) {
                wList = wList.stream().filter(p -> p.Status != 1 && p.Status != 2).collect(Collectors.toList());
            }

            if (wList != null && wList.size() > 0) {
                for (OMSOrder wOMSOrder : wList) {
                    int wCount = APSBOMItemDAO.getInstance().APS_QueryBOMItemCount(wLoginUser, wOMSOrder.ID,
                            wErrorCode);
                    wOMSOrder.IsCreateAPSBom = wCount > 0;
                }
                wResult.Result = wList;
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public synchronized void APS_AutoGenerateConfirmForm(BMSEmployee wLoginUser) {
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            List<Integer> wOrderIDList = OMSOrderDAO.getInstance()
                    .OMS_QueryNotGenerateConfirmFormOrderIDList(wLoginUser, wErrorCode);
            if (wOrderIDList == null || wOrderIDList.size() <= 0) {
                return;
            }

            for (Integer wOrderID : wOrderIDList) {
                SFCOrderForm wSFCOrderForm = new SFCOrderForm();

                OMSOrder wOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wOrderID, wErrorCode);

                wSFCOrderForm.CreateID = wLoginUser.ID;
                wSFCOrderForm.CreateTime = Calendar.getInstance();
                wSFCOrderForm.ID = 0;
                wSFCOrderForm.Type = SFCOrderFormType.CompleteConfirm.getValue();
                wSFCOrderForm.OrderID = wOrderID;
                wSFCOrderForm.OrderNo = wOrder.OrderNo;
                wSFCOrderForm.PartNo = wOrder.PartNo;
                wSFCOrderForm.Status = 1;

                SFCOrderFormDAO.getInstance().Update(wLoginUser, wSFCOrderForm, wErrorCode);
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    @Override
    public synchronized void APS_AutoFinishTaskPart(BMSEmployee wLoginUser) {
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            List<APSTaskPart> wList = APSTaskPartDAO.getInstance().APS_QueryFinishedTaskPartList(wLoginUser,
                    wErrorCode);
            if (wList == null || wList.size() <= 0) {
                return;
            }

            for (APSTaskPart wAPSTaskPart : wList) {
                wAPSTaskPart.Status = APSTaskStatus.Done.getValue();
                wAPSTaskPart.FinishWorkTime = Calendar.getInstance();

                APSTaskPartDAO.getInstance().Update(wLoginUser, wAPSTaskPart, wErrorCode);
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    @Override
    public List<AndonTime> ASP_QueryAndonTimeList(BMSEmployee wLoginUser, List<Integer> wOrderIDList) {
        List<AndonTime> wResult = new ArrayList<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wResult = APSTaskPartDAO.getInstance().APS_QueryAndonTime(wLoginUser, wOrderIDList, wErrorCode);
        } catch (Exception e) {
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<APSBOMItem>> APS_QueryQueryDeleteBomItemList(BMSEmployee wLoginUser, int wOrderID,
                                                                           int wPartID, String wMaterialNos) {
        ServiceResult<List<APSBOMItem>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            if (StringUtils.isEmpty(wMaterialNos)) {
                return wResult;
            }

            String[] wList = wMaterialNos.split(",");
            for (String wMaterialNo : wList) {
                wResult.Result.addAll(APSBOMItemDAO.getInstance().APS_QueryBOMItemList(wLoginUser, wOrderID, "", "", -1,
                        -1, -1, wPartID, -1, -1, wMaterialNo, -1, -1, -1, null, -1, -1, -1, wErrorCode));
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> APS_BOMTaskToSAP(BMSEmployee wLoginUser, int wBOMTaskID, List<Integer> wItemIDList,
                                                   int wLevelID) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            SFCBOMTask wTask = (SFCBOMTask) SFCBOMTaskDAO.getInstance().BPM_GetTaskInfo(wLoginUser, wBOMTaskID, "",
                    wErrorCode);

            OMSOrder wOMSOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wTask.OrderID, wErrorCode);

            // ①推送物料到SAP
            if (wTask.MaterialID > 0) {
                APSBOMItem wAPSBOMItem = CreateAPSBOMItem(wLoginUser, wTask, wErrorCode, wOMSOrder);
                APSServiceImpl.getInstance().APS_UpdateBOMItem(wLoginUser, wAPSBOMItem);
            }

            if (wLevelID > 0) {
                wTask.SFCBOMTaskItemList = wTask.SFCBOMTaskItemList.stream().filter(p -> p.Level == wLevelID)
                        .collect(Collectors.toList());
            }

            // ①推送物料到SAP(批量子表数据)
            if (wTask.SFCBOMTaskItemList.size() > 0) {
                List<SFCBOMTaskItem> wItemList = wTask.SFCBOMTaskItemList.stream().filter(p -> p.Status != 2)
                        .collect(Collectors.toList());

                if (wItemIDList != null && wItemIDList.size() > 0) {
                    wItemList = wItemList.stream().filter(p -> wItemIDList.stream().anyMatch(q -> q == p.ID))
                            .collect(Collectors.toList());
                }

                if (wItemList.size() <= 0) {
                    return wResult;
                }

                // 禁用之前的台车BOM
                DisableAPSBOM(wLoginUser, wItemList, wTask);

                // 推送给MES和SAP
                SynchronizedToSap(wLoginUser, wTask, wErrorCode, wItemList, wBOMTaskID);
            }
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    /**
     * 打上删除标记，台车BOM
     */
    private void DisableAPSBOM(BMSEmployee wLoginUser, List<SFCBOMTaskItem> wItemList, SFCBOMTask wTask) {
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            for (SFCBOMTaskItem wSFCBOMTaskItem : wItemList) {
                APSBOMItemDAO.getInstance().DeleteBOMX(wLoginUser, wTask.OrderID, wTask.PartID, wTask.PartPointID,
                        wSFCBOMTaskItem.MaterialID, wErrorCode);
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    private void SynchronizedToSap(BMSEmployee wLoginUser, SFCBOMTask wTask, OutResult<Integer> wErrorCode,
                                   List<SFCBOMTaskItem> wItemList, int wSFCBOMTaskID) {
        try {
            OMSOrder wOMSOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wTask.OrderID, wErrorCode);

            List<APSBOMItem> wList = CreateAPSBOMItemList(wLoginUser, wTask, wErrorCode, wOMSOrder, wItemList);

            if (wList.size() > 0) {
                ExecutorService wES = Executors.newFixedThreadPool(1);
                wES.submit(() -> APSServiceImpl.getInstance().APS_UpdateBOMItemList(wLoginUser, wList, wSFCBOMTaskID,
                        wTask.CovaType, wItemList));
                wES.shutdown();
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    /**
     * 创建台车bom集合
     */
    private List<APSBOMItem> CreateAPSBOMItemList(BMSEmployee wLoginUser, SFCBOMTask wTask,
                                                  OutResult<Integer> wErrorCode, OMSOrder wOMSOrder,
                                                  List<SFCBOMTaskItem> wItemList) {
        List<APSBOMItem> wResult = new ArrayList<>();
        try {
            if (wItemList == null || wItemList.size() <= 0) {
                return wResult;
            }

            for (SFCBOMTaskItem wSFCBOMTaskItem : wItemList) {
                APSBOMItem wAPSBOMItem = null;

                int wOutsourceType = 0;
                if (wSFCBOMTaskItem.BOMItemID > 0) {
                    // 提交到Core偶换件
                    MSSBOMItem wItem = WMSServiceImpl.getInstance()
                            .MSS_QueryBOMItemByID(wLoginUser, wSFCBOMTaskItem.BOMItemID).Info(MSSBOMItem.class);
                    wOutsourceType = wItem.OutsourceType;
                }
                wAPSBOMItem = new APSBOMItem();
                wAPSBOMItem.ID = 0;
                wAPSBOMItem.BOMType = 2;
                wAPSBOMItem.FactoryID = 1900;
                wAPSBOMItem.WBSNo = wOMSOrder.OrderNo;
                wAPSBOMItem.OrderID = wOMSOrder.ID;
                wAPSBOMItem.PartNo = wOMSOrder.PartNo;
                wAPSBOMItem.LineID = wOMSOrder.LineID;
                wAPSBOMItem.ProductID = wOMSOrder.ProductID;
                wAPSBOMItem.CustomerID = wOMSOrder.CustomerID;
                wAPSBOMItem.PartID = wTask.PartID;
                wAPSBOMItem.PartPointID = wTask.PartPointID;
                wAPSBOMItem.MaterialID = wSFCBOMTaskItem.MaterialID;
                wAPSBOMItem.MaterialNo = wSFCBOMTaskItem.MaterialNo;
                wAPSBOMItem.MaterialName = wSFCBOMTaskItem.MaterialName;
                wAPSBOMItem.Number = wSFCBOMTaskItem.MaterialNumber;
                wAPSBOMItem.UnitID = APSBOMItemDAO.getInstance().GetUnitID(wLoginUser, wSFCBOMTaskItem.MaterialID,
                        wErrorCode);
                wAPSBOMItem.ReplaceType = 2;
                wAPSBOMItem.OutsourceType = wOutsourceType;
                // 若是委外偶修件，需设置为互换件
                if (wOutsourceType == 2) {
                    wAPSBOMItem.PartChange = 1;
                }
                wAPSBOMItem.StockID = 1200;
                wAPSBOMItem.Status = 1;

                if (wSFCBOMTaskItem.SapType == 1) {
                    wAPSBOMItem.AssessmentType = "常规新件";
                } else if (wSFCBOMTaskItem.SapType == 2) {
                    wAPSBOMItem.AssessmentType = "修复旧件";
                } else if (wSFCBOMTaskItem.SapType == 3) {
                    wAPSBOMItem.AssessmentType = "可用旧件";
                } else if (wSFCBOMTaskItem.SapType == 4) {
                    wAPSBOMItem.AssessmentType = "高价互换件";
                }

                wAPSBOMItem.SourceType = APSBOMSourceType.SFCBOMTask.getValue();
                wAPSBOMItem.SourceID = wSFCBOMTaskItem.ID;
                wAPSBOMItem.AuditTime = Calendar.getInstance();
                wAPSBOMItem.EditTime = Calendar.getInstance();

                wAPSBOMItem.NewSourceID = wTask.ID;
                wAPSBOMItem.NewSourceCode = wTask.Code;
                wAPSBOMItem.ReviewComments = wSFCBOMTaskItem.ReviewComments;

                // ①加入质量损失
                if (StringUtils.isNotEmpty(wSFCBOMTaskItem.QualityLossBig)
                        || StringUtils.isNotEmpty(wSFCBOMTaskItem.QualityLossSmall)) {
                    wAPSBOMItem.BOMType = 9;
                    wAPSBOMItem.QTType = GetQTType(wSFCBOMTaskItem.QualityLossBig);
                    wAPSBOMItem.QTItemType = GetQTItemType(wSFCBOMTaskItem.QualityLossSmall);
                }

                wResult.add(wAPSBOMItem);
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
        return wResult;
    }

    /**
     * 获取质量损失小类
     */
    private int GetQTItemType(String qualityLossSmall) {
        int wResult = 0;
        try {
            switch (qualityLossSmall) {
                case "01":
                    wResult = 1;
                    break;
                case "02":
                    wResult = 2;
                    break;
                case "03":
                    wResult = 3;
                    break;
                case "04":
                    wResult = 4;
                    break;
                case "05":
                    wResult = 5;
                    break;
                default:
                    break;
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
        return wResult;
    }

    /**
     * 获取质量损失大类
     */
    private int GetQTType(String qualityLossBig) {
        int wResult = 0;
        try {
            switch (qualityLossBig) {
                case "001":
                    wResult = 1;
                    break;
                case "002":
                    wResult = 2;
                    break;
                case "003":
                    wResult = 3;
                    break;
                case "004":
                    wResult = 4;
                    break;
                default:
                    break;
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
        return wResult;
    }

    private APSBOMItem CreateAPSBOMItem(BMSEmployee wLoginUser, SFCBOMTask wTask, OutResult<Integer> wErrorCode,
                                        OMSOrder wOMSOrder) {
        APSBOMItem wAPSBOMItem = null;
        try {
            if (wTask.BOMItemID > 0) {
                // 提交到Core偶换件
                MSSBOMItem wItem = WMSServiceImpl.getInstance().MSS_QueryBOMItemByID(wLoginUser, wTask.BOMItemID)
                        .Info(MSSBOMItem.class);
                wItem.MaterialNumber = wTask.MaterialNumber;
                wAPSBOMItem = new APSBOMItem(wItem, wOMSOrder.LineID, wOMSOrder.ProductID, wOMSOrder.BureauSectionID,
                        wOMSOrder.ID, wOMSOrder.OrderNo, wOMSOrder.PartNo);
            } else {
                wAPSBOMItem = new APSBOMItem();
                wAPSBOMItem.ID = 0;
                wAPSBOMItem.BOMType = 2;
                wAPSBOMItem.FactoryID = 1900;
                wAPSBOMItem.WBSNo = wOMSOrder.OrderNo;
                wAPSBOMItem.OrderID = wOMSOrder.ID;
                wAPSBOMItem.PartNo = wOMSOrder.PartNo;
                wAPSBOMItem.LineID = wOMSOrder.LineID;
                wAPSBOMItem.ProductID = wOMSOrder.ProductID;
                wAPSBOMItem.CustomerID = wOMSOrder.CustomerID;
                wAPSBOMItem.PartID = wTask.PartID;
                wAPSBOMItem.PartPointID = wTask.PartPointID;
                wAPSBOMItem.MaterialID = wTask.MaterialID;
                wAPSBOMItem.MaterialNo = wTask.MaterialNo;
                wAPSBOMItem.Number = wTask.MaterialNumber;
                wAPSBOMItem.UnitID = APSBOMItemDAO.getInstance().GetUnitID(wLoginUser, wTask.MaterialID, wErrorCode);
                wAPSBOMItem.ReplaceType = 2;
                wAPSBOMItem.StockID = 1200;
                wAPSBOMItem.Status = 1;
            }

            if (wTask.SapType == 1) {
                wAPSBOMItem.AssessmentType = "常规新件";
            } else if (wTask.SapType == 2) {
                wAPSBOMItem.AssessmentType = "修复旧件";
            }
            wAPSBOMItem.SourceType = APSBOMSourceType.SFCBOMTask.getValue();
            wAPSBOMItem.SourceID = wTask.ID;
            wAPSBOMItem.AuditTime = Calendar.getInstance();
            wAPSBOMItem.EditTime = Calendar.getInstance();
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
        return wAPSBOMItem;
    }

    @Override
    public ServiceResult<List<APSDayPlanAuditBPM>> APS_QueryDayPlanAuditBPMEmployeeAllWeb(BMSEmployee wLoginUser,
                                                                                          Calendar wStartTime,
                                                                                          Calendar wEndTime,
                                                                                          int wStatus, int wAreaID) {
        ServiceResult<List<APSDayPlanAuditBPM>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            switch (wStatus) {
                case 1:
                    wResult.Result.addAll(APSDayPlanAuditBPMDAO.getInstance().SelectList(wLoginUser, -1, "", -1, "",
                            -1, -1,
                            new ArrayList<>(Arrays.asList(20, 21, 22)), wStartTime, wEndTime, wErrorCode));
                    break;
                case 0:
                    wResult.Result.addAll(APSDayPlanAuditBPMDAO.getInstance().SelectList(wLoginUser, -1, "", -1, "",
                            -1, -1,
                            new ArrayList<>(Arrays.asList(1, 2)), wStartTime, wEndTime, wErrorCode));
                    break;
                default:
                    wResult.Result.addAll(APSDayPlanAuditBPMDAO.getInstance().SelectList(wLoginUser, -1, "", -1, "",
                            -1, -1,
                            new ArrayList<>(Arrays.asList(1, 2, 3, 20, 21, 22)), wStartTime, wEndTime,
                            wErrorCode));
                    break;
            }
            wResult.Result.sort((o1, o2) -> o2.SubmitTime.compareTo(o1.SubmitTime));

            if (wAreaID > 0) {
                wResult.Result = wResult.Result.stream().filter(p -> p.AreaID == wAreaID).collect(Collectors.toList());
            }

            if (wResult.Result.size() <= 0 || wStatus == 1) {
                return wResult;
            }

            // 待办数据处理
            List<BPMTaskBase> wBaseList = APSDayPlanAuditBPMDAO.getInstance().BPM_GetUndoTaskList(wLoginUser,
                    wLoginUser.getID(), wErrorCode);
            if (wBaseList == null || wBaseList.size() <= 0) {
                return wResult;
            }
            for (BPMTaskBase wTaskBase : wBaseList) {
                if (!(wTaskBase instanceof APSDayPlanAuditBPM))
                    continue;
                APSDayPlanAuditBPM wIPTStandardBPM = (APSDayPlanAuditBPM) wTaskBase;
                wIPTStandardBPM.TagTypes = TaskQueryType.ToHandle.getValue();
                for (int i = 0; i < wResult.Result.size(); i++) {
                    if (wResult.Result.get(i).ID == wIPTStandardBPM.ID)
                        wResult.Result.set(i, wIPTStandardBPM);
                }
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<String> APS_SendMoreToSAP(BMSEmployee wLoginUser, List<MSSBOMItem> wDataList) {
        ServiceResult<String> wResult = new ServiceResult<>();
        wResult.Result = "";
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            List<OMSOrder> wOrderList = OMSOrderDAO.getInstance().GetListByBOMID(wLoginUser, wDataList.get(0).BOMID,
                    wErrorCode);

            for (OMSOrder wOrder : wOrderList) {
                List<APSBOMItem> wResultList = new ArrayList<>();

                APSBOMItem wBOMItem = null;

                for (MSSBOMItem wMSSBOMItem : wDataList) {

                    if (wMSSBOMItem.Active != 1)
                        continue;

                    if (wMSSBOMItem.ReplaceType == 1
                            || (wMSSBOMItem.ReplaceType != 2 && wMSSBOMItem.OutsourceType == 1)) {

                        wBOMItem = new APSBOMItem(wMSSBOMItem, wOrder.LineID, wOrder.ProductID, wOrder.BureauSectionID,
                                wOrder.ID, wOrder.OrderNo, wOrder.PartNo);

                        wBOMItem.ProductNo = wOrder.ProductNo;
                        wBOMItem.LineName = wOrder.LineName;
                        wBOMItem.CustomerCode = APSConstans.GetCRMCustomer(wOrder.BureauSectionID).CustomerCode;
                        wBOMItem.SourceType = APSBOMSourceType.StandardBOM.getValue();
                        wBOMItem.SourceID = wMSSBOMItem.ID;
                        wBOMItem.AuditorID = wLoginUser.ID;
                        wBOMItem.EditorID = wLoginUser.ID;
                        wBOMItem.AuditTime = Calendar.getInstance();
                        wBOMItem.EditTime = Calendar.getInstance();

                        wResultList.add(wBOMItem);
                    }
                }

                if (wResultList.size() <= 0) {
                    wResult.FaultCode += "提示：无必换件或委外必修件!";
                    return wResult;
                }

                // 验证台车BOM
                String wMsg = APSBOMUtils.getInstance().CheckAPSBOM(wResultList, wOrder);
                if (StringUtils.isNotEmpty(wMsg)) {

                    List<BFCMessage> wBFCMessageList = new ArrayList<>();
                    BFCMessage wMessage = null;
                    int wShiftID = MESServer.MES_QueryShiftID(wLoginUser.CompanyID, Calendar.getInstance(),
                            APSShiftPeriod.Day, FMCShiftLevel.Day, 0);
                    // 发送任务消息到人员
                    wMessage = new BFCMessage();
                    wMessage.Active = 0;
                    wMessage.CompanyID = 0;
                    wMessage.CreateTime = Calendar.getInstance();
                    wMessage.EditTime = Calendar.getInstance();
                    wMessage.ID = 0;
                    wMessage.MessageID = 0;
                    wMessage.Title = StringUtils.Format("【台车BOM】提示", BPMEventModule.StationTip.getLable());
                    wMessage.MessageText = wMsg;
                    wMessage.ModuleID = BPMEventModule.StationTip.getValue();
                    wMessage.ResponsorID = StringUtils
                            .parseInt(Configuration.readConfigString("bomUser", "config/config"));
                    wMessage.ShiftID = wShiftID;
                    wMessage.StationID = 0;
                    wMessage.Type = BFCMessageType.Notify.getValue();
                    wBFCMessageList.add(wMessage);

                    CoreServiceImpl.getInstance().BFC_UpdateMessageList(wLoginUser, wBFCMessageList);

                    // 返回提示信息
                    wResult.FaultCode = wMsg;
                    return wResult;
                }

                // 重新编号保存
                for (APSBOMItem wAPSBOMItem : wResultList) {
                    wAPSBOMItem.OrderNum = APSBOMItemDAO.getInstance().APS_QueryOrdrNumber(wLoginUser,
                            wAPSBOMItem.OrderID, wErrorCode);
                    wAPSBOMItem.ID = APSBOMItemDAO.getInstance().APS_UpdateBOMItem(wLoginUser, wAPSBOMItem, wErrorCode);
                }

                // 评估类型赋值
                wResultList.forEach(p -> {
                    if (p.OutsourceType == 1) {
                        p.AssessmentType = "修复旧件";
                    }
                });

                String wReturnMsg = "";
                String wSendSAP = Configuration.readConfigString("isSendSAP", "config/config");
                if (wSendSAP.equals("1")) {
                    // ①推送台车BOM给SAP
                    String wJson = APSBOMUtils.getInstance().ChangeToJson(wResultList, "U");
                    if (StringUtils.isNotEmpty(wJson)) {
                        wReturnMsg = SendToSAP(wLoginUser, wJson, wOrder.OrderNo, 0, wOrder, 0, null, 2);
                    }
                }
                wResult.Result += StringUtils.Format("【{0}】{1}。", wOrder.PartNo, wReturnMsg);
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<String> IPT_ImportAPSBOM(BMSEmployee wLoginUser, ExcelData wExcelData,
                                                  String wOriginalFileName, int wOrderID) {
        ServiceResult<String> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            OMSOrder wOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wOrderID, wErrorCode);

            List<APSBOMItem> wList = new ArrayList<>();

            int wIndex = 1;
            for (ExcelSheetData wExcelSheetData : wExcelData.sheetData) {
                for (int i = 2; i < wExcelSheetData.lineData.size(); i++) {
                    APSBOMItem wAPSBOMItem = new APSBOMItem();

                    wAPSBOMItem.ID = 0;
                    wAPSBOMItem.BOMType = 2;
                    wAPSBOMItem.FactoryID = 1900;
                    wAPSBOMItem.WBSNo = wOrder.OrderNo;
                    wAPSBOMItem.OrderID = wOrder.ID;
                    wAPSBOMItem.PartNo = wOrder.PartNo;
                    wAPSBOMItem.LineID = wOrder.LineID;
                    wAPSBOMItem.ProductID = wOrder.ProductID;
                    wAPSBOMItem.CustomerID = wOrder.CustomerID;
                    wAPSBOMItem.PartID = APSConstans.GetPartIDByCode(wExcelSheetData.lineData.get(i).colData.get(4));

                    String wStepName = wExcelSheetData.lineData.get(i).colData.get(38).split(" {2}")[1];

                    wAPSBOMItem.PartPointID = APSConstans.GetPartPointIDByName(wStepName);
                    wAPSBOMItem.MaterialID = GetMaterialID(wLoginUser, wExcelSheetData.lineData.get(i).colData.get(7));
                    wAPSBOMItem.MaterialNo = wExcelSheetData.lineData.get(i).colData.get(7);
                    wAPSBOMItem.Number = StringUtils.parseDouble(wExcelSheetData.lineData.get(i).colData.get(12));
                    wAPSBOMItem.UnitID = APSConstans.GetCFGUnit(wExcelSheetData.lineData.get(i).colData.get(13)).ID;
                    wAPSBOMItem.ReplaceType = StringUtils.parseInt(wExcelSheetData.lineData.get(i).colData.get(24));
                    wAPSBOMItem.OutsourceType = StringUtils.parseInt(wExcelSheetData.lineData.get(i).colData.get(27));
                    wAPSBOMItem.OriginalType = 0;
                    wAPSBOMItem.DisassyType = 0;
                    wAPSBOMItem.OverLine = 0;
                    wAPSBOMItem.PartChange = 0;
                    wAPSBOMItem.ReceiveDepart = "0001";
                    wAPSBOMItem.StockID = 1200;
                    wAPSBOMItem.QTType = 0;
                    wAPSBOMItem.QTItemType = 0;
                    wAPSBOMItem.CustomerMaterial = 0;
                    wAPSBOMItem.AuditorID = 0;
                    wAPSBOMItem.AuditTime = Calendar.getInstance();
                    wAPSBOMItem.EditorID = 0;
                    wAPSBOMItem.EditTime = Calendar.getInstance();
                    wAPSBOMItem.Status = 1;
                    wAPSBOMItem.RelaDemandNo = wExcelSheetData.lineData.get(i).colData.get(0);
                    wAPSBOMItem.TextCode = wExcelSheetData.lineData.get(i).colData.get(34);
                    wAPSBOMItem.WorkCenter = "";
                    wAPSBOMItem.DeleteID = wExcelSheetData.lineData.get(i).colData.get(33);
                    wAPSBOMItem.SubRelaDemandNo = wExcelSheetData.lineData.get(i).colData.get(1);
                    wAPSBOMItem.AssessmentType = wExcelSheetData.lineData.get(i).colData.get(6);
                    wAPSBOMItem.AccessoryLogo = "";
                    wAPSBOMItem.RepairPartClass = "";
                    wAPSBOMItem.Remark = wExcelSheetData.lineData.get(i).colData.get(31);
                    wAPSBOMItem.DingrongGroup = "";
                    wAPSBOMItem.RepairCoreIdentification = "";
                    wAPSBOMItem.PickingQuantity = 0;
                    wAPSBOMItem.EvenExchangeRate = 0;
                    wAPSBOMItem.Client = "";
                    wAPSBOMItem.OrderNum = wIndex++;
                    wAPSBOMItem.SourceType = APSBOMSourceType.StandardBOM.getValue();
                    wAPSBOMItem.SourceID = 0;
                    wAPSBOMItem.DifferenceItem = 0;
                    wAPSBOMItem.OverQuota = 0;

                    wList.add(wAPSBOMItem);
                }
            }

            APSBOMItemDAO.getInstance().APS_CreateBOMItem(wLoginUser, wList, wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    /**
     * 获取物料ID
     */
    private int GetMaterialID(BMSEmployee wLoginUser, String wNo) {
        int wResult = 0;
        try {
            if (StringUtils.isEmpty(wNo)) {
                return wResult;
            }

            List<MSSMaterial> wList = WMSServiceImpl.getInstance().MSS_QueryMaterialList(wLoginUser, wNo)
                    .List(MSSMaterial.class);
            if (wList == null || wList.size() <= 0) {
                return wResult;
            }

            wResult = wList.get(0).ID;
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> APS_BOMItemUpdateProperty(BMSEmployee wBMSEmployee, APSBOMItem wBOMItem) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            // 根据订单ID，工位、工序、物料ID 查询物料
            APSBOMItem wItem = APSBOMItemDAO.getInstance().APS_SelectItem(wBMSEmployee, wBOMItem.OrderID,
                    wBOMItem.PartID, wBOMItem.PartPointID, wBOMItem.MaterialID, wBOMItem.ReplaceType,
                    wBOMItem.OutsourceType, wErrorCode);
            if (wItem != null && wItem.ID > 0) {
                wItem.Number = wBOMItem.Number;
                wResult.Result = APSBOMItemDAO.getInstance().APS_UpdateBOMItem(wBMSEmployee, wItem, wErrorCode);

                // 推送给SAP(更新)
                if (wBOMItem.OrderID > 0) {
                    wBOMItem.SAPMsg = APSServiceImpl.getInstance().APS_UpdateBomItemByBOMItem(BaseDAO.SysAdmin,
                            wResult.Result).Result;
                }
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> APS_CompleteConfirm_V2(BMSEmployee wLoginUser, int wOrderID,
                                                         List<String> wImagePathList, String wRemark,
                                                         List<OMSOrderLessQuestionItem> wOMSOrderLessQuestionItemList) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            OMSOrder wOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wOrderID, wErrorCode);

            if (wOrder.Status != OMSOrderStatus.Repairing.getValue()) {
                wResult.FaultCode += "提示：请选择状态为“维修中”的订单!";
                return wResult;
            }

            // ①判断非线上车，竣工确认
            boolean wCheckResult = OMSOrderDAO.getInstance().IsOffLineBoarding(wLoginUser, wOrderID, wErrorCode);
            if (wCheckResult) {
                SFCOrderForm wSFCOrderForm = new SFCOrderForm();

                wSFCOrderForm.ID = 0;
                wSFCOrderForm.CreateID = wLoginUser.ID;
                wSFCOrderForm.Creator = wLoginUser.Name;
                wSFCOrderForm.OrderID = wOrderID;
                wSFCOrderForm.OrderNo = wOrder.OrderNo;
                wSFCOrderForm.PartNo = wOrder.PartNo;
                wSFCOrderForm.ProductNo = wOrder.ProductNo;
                wSFCOrderForm.Type = SFCOrderFormType.CompleteConfirm.getValue();

                wSFCOrderForm.CreateTime = Calendar.getInstance();
                wSFCOrderForm.ConfirmID = wLoginUser.ID;
                wSFCOrderForm.ConfirmTime = Calendar.getInstance();
                wSFCOrderForm.Status = 2;

                if (wImagePathList != null && wImagePathList.size() > 0) {
                    wSFCOrderForm.ImagePathList = wImagePathList;
                }

                if (StringUtils.isNotEmpty(wRemark)) {
                    wSFCOrderForm.Remark = wRemark;
                }

                SFCOrderFormDAO.getInstance().Update(wLoginUser, wSFCOrderForm, wErrorCode);

                wOrder.Status = OMSOrderStatus.FinishedWork.getValue();
                wOrder.RealFinishDate = Calendar.getInstance();
                OMSOrderDAO.getInstance().Update(BaseDAO.SysAdmin, wOrder, wErrorCode);

                return wResult;
            }

            // ⑩生成竣工确认单，且将订单状态改为已完工
            // List<SFCOrderForm> wOrderList =
            // SFCOrderFormDAO.getInstance().SelectList(wLoginUser, -1, wOrder.ID, "", 1,
            // null, wErrorCode);
            // if (wOrderList == null || wOrderList.size() <= 0) {
            // wResult.FaultCode += "提示：该订单未完成终检，无法进行竣工确认!";
            // return wResult;
            // }

            // 保存返修和不合格评审
            OMSServiceImpl.getInstance().OMS_SaveOrderFilterQuestionItems(wLoginUser, wOMSOrderLessQuestionItemList,
                    wOrderID);

            // ⑧检查该订单的不合格评审单是否全部完成
            List<Integer> wFilterNCRTaskIDList = wOMSOrderLessQuestionItemList.stream()
                    .filter(p -> p.Type == OMSOrderLessQuestionType.UnqualifiedReview.getValue()).map(p -> p.ID)
                    .distinct().collect(Collectors.toList());
            int wNCRNumber = AndonDAO.getInstance().SelectNcrCountNF(wLoginUser, wOrder.ID, wFilterNCRTaskIDList,
                    wErrorCode);
            if (wNCRNumber > 0) {
                wResult.FaultCode += "提示：该订单有未完成的不合格评审单!";
                return wResult;
            }
            // ⑨检查该订单的返修单是否全部完成
            List<Integer> wFilterRepairTaskIDList = wOMSOrderLessQuestionItemList.stream()
                    .filter(p -> p.Type == OMSOrderLessQuestionType.Repair.getValue()).map(p -> p.ID).distinct()
                    .collect(Collectors.toList());
            int wRepairNumber = AndonDAO.getInstance().SelectRepairCountNF(wLoginUser, wOrder.ID,
                    wFilterRepairTaskIDList, wErrorCode);
            if (wRepairNumber > 0) {
                wResult.FaultCode += "提示：该订单有未完成的返修单!";
                return wResult;
            }

            // APSTaskPart wTaskPart =
            // AndonDAO.getInstance().SelectNotFinishTaskPart(wLoginUser, wOrder.ID,
            // wErrorCode);
            // 查询未完成的工序任务
            APSTaskStep wTaskStep = AndonDAO.getInstance().QueryUnfinishedOperationTasks(wLoginUser, wOrderID,
                    wErrorCode);
            if (StringUtils.isNotEmpty(wTaskStep.PartName) && !wTaskStep.PartName.contains("出厂普查")) {
                wResult.FaultCode += StringUtils.Format("提示：【{0}】-【{1}】工序任务未完成!", wTaskStep.PartName,
                        wTaskStep.StepName);
                return wResult;
            }

            // 生成竣工确认单
            List<SFCOrderForm> wOrderList = SFCOrderFormDAO.getInstance().SelectList(wLoginUser, -1, wOrder.ID, "", 1,
                    null, wErrorCode);
            SFCOrderForm wSFCOrderForm = new SFCOrderForm();
            if (wOrderList.size() > 0) {
                wSFCOrderForm = wOrderList.get(0);
            } else {
                wSFCOrderForm.ID = 0;
                wSFCOrderForm.OrderNo = wOrder.OrderNo;
                wSFCOrderForm.OrderID = wOrderID;
                wSFCOrderForm.CreateID = wLoginUser.ID;
                wSFCOrderForm.CreateTime = Calendar.getInstance();
                wSFCOrderForm.Type = SFCOrderFormType.CompleteConfirm.getValue();
            }
            wSFCOrderForm.ConfirmID = wLoginUser.ID;
            wSFCOrderForm.ConfirmTime = Calendar.getInstance();
            wSFCOrderForm.Status = 2;
            if (wImagePathList != null && wImagePathList.size() > 0) {
                wSFCOrderForm.ImagePathList = wImagePathList;
            }
            if (StringUtils.isNotEmpty(wRemark)) {
                wSFCOrderForm.Remark = wRemark;
            }
            SFCOrderFormDAO.getInstance().Update(wLoginUser, wSFCOrderForm, wErrorCode);

            wOrder.Status = OMSOrderStatus.FinishedWork.getValue();
            if (wOMSOrderLessQuestionItemList.size() > 0) {
                wOrder.Status = OMSOrderStatus.PartConfirmed.getValue();
            }
            wOrder.RealFinishDate = Calendar.getInstance();
            OMSOrderDAO.getInstance().Update(BaseDAO.SysAdmin, wOrder, wErrorCode);

            // 台车完工时，mes检索完工车所有的物料配送单，待分拣的，走取消接口，全部取消，并备注原因“完工车取消”(以区分正常取消与完工车取消)
            ExecutorService wES = Executors.newFixedThreadPool(1);
            wES.submit(() -> MyHelperServiceImpl.getInstance().WMS_CancelPickDemandListByFinishedOrder(wLoginUser,
                    wOrder, wErrorCode));
            wES.shutdown();

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public synchronized ServiceResult<Integer> APS_UpdateBOMItemList(BMSEmployee wLoginUser, List<APSBOMItem> wDataList,
                                                                     int wSFCBOMTaskID, int wCovaType,
                                                                     List<SFCBOMTaskItem> wItemList) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            // 处理数据
            for (APSBOMItem wBOMItem : wDataList) {
                // 判断是否为差异项
                wBOMItem.DifferenceItem = APSBOMItemDAO.getInstance().JudgeIsDifferenceItem(wLoginUser, wBOMItem,
                        wErrorCode);

                if (wBOMItem.SourceType != APSBOMSourceType.SFCBOMTask.getValue()) {
                    if (wBOMItem.ReplaceType == 1 || wBOMItem.ReplaceType == 2) {
                        wBOMItem.AssessmentType = "常规新件";
                    }
                    if (wBOMItem.OutsourceType == 1 || wBOMItem.OutsourceType == 2) {
                        wBOMItem.AssessmentType = "修复旧件";
                    }
                    if (wBOMItem.PartChange > 0) {
                        wBOMItem.AssessmentType = "修复旧件";
                    }
                    if (wBOMItem.ReplaceType != 1 && (wBOMItem.OutsourceType == 3 || wBOMItem.OutsourceType == 4)) {
                        wBOMItem.AssessmentType = "可用旧件";
                    }
                    if (wBOMItem.ReplaceType == 1 && wBOMItem.OutsourceType == 1) {
                        wBOMItem.AssessmentType = "常规新件";
                    }
                }
            }

            OMSOrder wOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wDataList.get(0).OrderID, wErrorCode);

            // 验证台车BOM
            String wMsg = APSBOMUtils.getInstance().CheckAPSBOM(wDataList, wOrder);

            if (StringUtils.isNotEmpty(wMsg)) {

                List<BFCMessage> wBFCMessageList = new ArrayList<>();
                BFCMessage wMessage = null;
                int wShiftID = MESServer.MES_QueryShiftID(wLoginUser.CompanyID, Calendar.getInstance(),
                        APSShiftPeriod.Day, FMCShiftLevel.Day, 0);
                // 发送任务消息到人员
                wMessage = new BFCMessage();
                wMessage.Active = 0;
                wMessage.CompanyID = 0;
                wMessage.CreateTime = Calendar.getInstance();
                wMessage.EditTime = Calendar.getInstance();
                wMessage.ID = 0;
                wMessage.MessageID = 0;
                wMessage.Title = StringUtils.Format("【台车BOM】提示", BPMEventModule.StationTip.getLable());
                wMessage.MessageText = wMsg;
                wMessage.ModuleID = BPMEventModule.StationTip.getValue();
                wMessage.ResponsorID = StringUtils.parseInt(Configuration.readConfigString("bomUser", "config/config"));
                wMessage.ShiftID = wShiftID;
                wMessage.StationID = 0;
                wMessage.Type = BFCMessageType.Notify.getValue();
                wBFCMessageList.add(wMessage);

                CoreServiceImpl.getInstance().BFC_UpdateMessageList(wLoginUser, wBFCMessageList);

                // 维护SAP推送状态
                if (wSFCBOMTaskID > 0) {
                    ExecutorService wES = Executors.newFixedThreadPool(1);
                    wES.submit(() -> UpdateSFCBOMTaskSAPStatus(wLoginUser, wMsg, wSFCBOMTaskID));
                    wES.shutdown();
                }

                // 返回提示信息
                wResult.FaultCode = wMsg;
                return wResult;
            }

            // 保存到MES系统数据库
            for (APSBOMItem wBOMItem : wDataList) {
                wBOMItem.ID = APSBOMItemDAO.getInstance().APS_UpdateBOMItem(wLoginUser, wBOMItem, wErrorCode);
                wBOMItem.ProductNo = wOrder.ProductNo;
                wBOMItem.LineName = wOrder.LineName;
                wBOMItem.CustomerCode = APSConstans.GetCRMCustomer(wBOMItem.CustomerID).CustomerCode;
                wBOMItem.PartPointName = APSConstans.GetFPCPartPointName(wBOMItem.PartPointID);
            }

            String wSendSAP = Configuration.readConfigString("isSendSAP", "config/config");

            if (wSendSAP.equals("1")) {
                // ①质量损失的数据分开发送
                List<APSBOMItem> wQualityLossList = wDataList.stream().filter(p -> p.BOMType == 9)
                        .collect(Collectors.toList());
                List<APSBOMItem> wNormalList = wDataList.stream().filter(p -> p.BOMType != 9)
                        .collect(Collectors.toList());

                if (wQualityLossList.size() > 0) {
                    // 判断是否已经有质量损失，若没有，用I创建，若有，用U更新
                    boolean wIsExist = SFCBOMTaskDAO.getInstance().IsExistQualityLoss(wLoginUser, wOrder, wErrorCode);
                    int wUpdateType = 2;
                    String wUpChar = "U";
                    if (!wIsExist) {
                        wUpChar = "I";
                        wUpdateType = 1;
                    }

                    // ①推送台车BOM给SAP
                    String wJson = APSBOMUtils.getInstance().ChangeToJson(wQualityLossList, wUpChar);
                    if (StringUtils.isNotEmpty(wJson)) {
                        String wRst = SendToSAP(wLoginUser, wJson, wOrder.OrderNo, wSFCBOMTaskID, wOrder, 0,
                                wQualityLossList.stream().map(p -> p.ID).distinct().collect(Collectors.toList()),
                                wUpdateType);
                        if (wRst.contains("成功")) {
                            List<APSBOMItem> wCloneList = CloneTool.CloneArray(wQualityLossList, APSBOMItem.class);
                            if (wCovaType == 1) {
                                // 线边库消耗
                                // ERP过账
                                WMSServiceImpl.getInstance().WMS_LineEdgeCovaUse(wLoginUser, wItemList, wCloneList);
                            } else {
                                if (wSFCBOMTaskID > 0) {
                                    // 判断是否已经创建物料配送到单，若是，则返回，不创建
                                    boolean wIsCreated = SFCBOMTaskDAO.getInstance().JudgeIsCreated(wLoginUser,
                                            wSFCBOMTaskID,
                                            wItemList.get(0).MaterialID, wErrorCode);
                                    if (wIsCreated) {
                                        return wResult;
                                    }
                                }

                                // 创建物料配送单
                                wCloneList.removeIf(p -> p.AssessmentType.equals("修复旧件") &&
                                        p.ReviewComments == SFCBOMTaskReviewComments.Repair.getValue()
                                        && (p.OutsourceType == 1 || p.OutsourceType == 2));
                                if (wCloneList.size() > 0) {
                                    CreatePSD(wLoginUser, wCloneList, wSFCBOMTaskID, wErrorCode);
                                }
                            }
                        }
                    }
                }

                if (wNormalList.size() > 0) {
                    // ①推送台车BOM给SAP
                    String wJson = APSBOMUtils.getInstance().ChangeToJson(wNormalList, "U");
                    if (StringUtils.isNotEmpty(wJson)) {
                        String wRst = SendToSAP(wLoginUser, wJson, wOrder.OrderNo, wSFCBOMTaskID, wOrder, 0,
                                wNormalList.stream().map(p -> p.ID).distinct().collect(Collectors.toList()), 2);
                        if (wRst.contains("变更成功")) {
                            List<APSBOMItem> wCloneList = CloneTool.CloneArray(wNormalList, APSBOMItem.class);
                            if (wCovaType == 1) {
                                // 线边库消耗
                                // ERP过账
                                WMSServiceImpl.getInstance().WMS_LineEdgeCovaUse(wLoginUser, wItemList, wCloneList);
                            } else {
                                if (wSFCBOMTaskID > 0) {
                                    // 判断是否已经创建物料配送到单，若是，则返回，不创建
                                    boolean wIsCreated = SFCBOMTaskDAO.getInstance().JudgeIsCreated(wLoginUser,
                                            wSFCBOMTaskID,
                                            wItemList.get(0).MaterialID, wErrorCode);
                                    if (wIsCreated) {
                                        return wResult;
                                    }
                                }

                                // 筛选 委外的领料单，进行委外领料
                                List<APSBOMItem> wOutsourceList = wCloneList.stream()
                                        .filter(p -> p.AssessmentType.equals("修复旧件")
                                                && p.ReviewComments == SFCBOMTaskReviewComments.Repair.getValue()
                                                && (p.OutsourceType == 1 || p.OutsourceType == 2))
                                        .collect(Collectors.toList());

                                if (wOutsourceList.size() > 0) {
                                    CreatePSD_Out(wLoginUser, wOutsourceList, wSFCBOMTaskID, wErrorCode);
                                }

                                // 创建物料配送单
                                wCloneList.removeIf(p -> p.AssessmentType.equals("修复旧件") &&
                                        p.ReviewComments == SFCBOMTaskReviewComments.Repair.getValue()
                                        && (p.OutsourceType == 1 || p.OutsourceType == 2));
                                if (wCloneList.size() > 0) {
                                    CreatePSD(wLoginUser, wCloneList, wSFCBOMTaskID, wErrorCode);
                                }
                            }
                        }
                    }
                }
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> APS_UpdateBOMItemList(BMSEmployee wLoginUser, List<APSBOMItem> wDataList,
                                                        int wSFCScrapApprovalBPMID,
                                                        List<SFCScrapApprovalBPMItem> wItemList) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            // 处理数据
            for (APSBOMItem wBOMItem : wDataList) {
                // 判断是否为差异项
                wBOMItem.DifferenceItem = APSBOMItemDAO.getInstance().JudgeIsDifferenceItem(wLoginUser, wBOMItem,
                        wErrorCode);

                if (wBOMItem.SourceType != APSBOMSourceType.SFCBOMTask.getValue()) {
                    if (wBOMItem.ReplaceType == 1 || wBOMItem.ReplaceType == 2) {
                        wBOMItem.AssessmentType = "常规新件";
                    }
                    if (wBOMItem.OutsourceType == 1 || wBOMItem.OutsourceType == 2) {
                        wBOMItem.AssessmentType = "修复旧件";
                    }
                    if (wBOMItem.PartChange > 0) {
                        wBOMItem.AssessmentType = "修复旧件";
                    }
                    if (wBOMItem.ReplaceType != 1 && (wBOMItem.OutsourceType == 3 || wBOMItem.OutsourceType == 4)) {
                        wBOMItem.AssessmentType = "可用旧件";
                    }
                    if (wBOMItem.ReplaceType == 1 && wBOMItem.OutsourceType == 1) {
                        wBOMItem.AssessmentType = "常规新件";
                    }
                }
            }

            OMSOrder wOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wDataList.get(0).OrderID, wErrorCode);

            // 验证台车BOM
            String wMsg = APSBOMUtils.getInstance().CheckAPSBOM(wDataList, wOrder);

            if (StringUtils.isNotEmpty(wMsg)) {

                List<BFCMessage> wBFCMessageList = new ArrayList<>();
                BFCMessage wMessage = null;
                int wShiftID = MESServer.MES_QueryShiftID(wLoginUser.CompanyID, Calendar.getInstance(),
                        APSShiftPeriod.Day, FMCShiftLevel.Day, 0);
                // 发送任务消息到人员
                wMessage = new BFCMessage();
                wMessage.Active = 0;
                wMessage.CompanyID = 0;
                wMessage.CreateTime = Calendar.getInstance();
                wMessage.EditTime = Calendar.getInstance();
                wMessage.ID = 0;
                wMessage.MessageID = 0;
                wMessage.Title = StringUtils.Format("【台车BOM】提示", BPMEventModule.StationTip.getLable());
                wMessage.MessageText = wMsg;
                wMessage.ModuleID = BPMEventModule.StationTip.getValue();
                wMessage.ResponsorID = StringUtils.parseInt(Configuration.readConfigString("bomUser", "config/config"));
                wMessage.ShiftID = wShiftID;
                wMessage.StationID = 0;
                wMessage.Type = BFCMessageType.Notify.getValue();
                wBFCMessageList.add(wMessage);

                CoreServiceImpl.getInstance().BFC_UpdateMessageList(wLoginUser, wBFCMessageList);

                // 维护SAP推送状态
                if (wSFCScrapApprovalBPMID > 0) {
                    ExecutorService wES = Executors.newFixedThreadPool(1);
                    wES.submit(() -> UpdateSFCScrapApprovalBPMSAPStatus(wLoginUser, wMsg, wSFCScrapApprovalBPMID));
                    wES.shutdown();
                }

                // 返回提示信息
                wResult.FaultCode = wMsg;
                return wResult;
            }

            // 保存到MES系统数据库
            for (APSBOMItem wBOMItem : wDataList) {
                wBOMItem.ID = APSBOMItemDAO.getInstance().APS_UpdateBOMItem(wLoginUser, wBOMItem, wErrorCode);
                wBOMItem.ProductNo = wOrder.ProductNo;
                wBOMItem.LineName = wOrder.LineName;
                wBOMItem.CustomerCode = APSConstans.GetCRMCustomer(wBOMItem.CustomerID).CustomerCode;
                wBOMItem.PartPointName = APSConstans.GetFPCPartPointName(wBOMItem.PartPointID);
            }

            String wSendSAP = Configuration.readConfigString("isSendSAP", "config/config");

            if (wSendSAP.equals("1")) {
                // ①质量损失的数据分开发送
                List<APSBOMItem> wQualityLossList = wDataList.stream().filter(p -> p.BOMType == 9)
                        .collect(Collectors.toList());
                List<APSBOMItem> wNormalList = wDataList.stream().filter(p -> p.BOMType != 9)
                        .collect(Collectors.toList());

                if (wQualityLossList.size() > 0) {
                    // 判断是否已经有质量损失，若没有，用I创建，若有，用U更新
                    boolean wIsExist = SFCBOMTaskDAO.getInstance().IsExistQualityLoss(wLoginUser, wOrder, wErrorCode);
                    int wUpdateType = 2;
                    String wUpChar = "U";
                    if (!wIsExist) {
                        wUpChar = "I";
                        wUpdateType = 1;
                    }

                    // ①推送台车BOM给SAP
                    String wJson = APSBOMUtils.getInstance().ChangeToJson(wQualityLossList, wUpChar);
                    if (StringUtils.isNotEmpty(wJson)) {
                        String wRst = SendToSAP(wLoginUser, wJson, wOrder.OrderNo, wSFCScrapApprovalBPMID, wOrder, 2,
                                wQualityLossList.stream().map(p -> p.ID).distinct().collect(Collectors.toList()),
                                wUpdateType);
                        if (wRst.contains("成功")) {
                            List<APSBOMItem> wCloneList = CloneTool.CloneArray(wQualityLossList, APSBOMItem.class);
                            // 创建物料配送单
                            wCloneList.removeIf(p -> p.AssessmentType.equals("修复旧件") &&
                                    p.ReviewComments == SFCBOMTaskReviewComments.Repair.getValue()
                                    && (p.OutsourceType == 1 || p.OutsourceType == 2));
                            if (wCloneList.size() > 0) {
                                CreatePSD_Scrap(wLoginUser, wCloneList, wSFCScrapApprovalBPMID, wErrorCode);
                            }
                        }
                    }
                }

                if (wNormalList.size() > 0) {
                    // ①推送台车BOM给SAP
                    String wJson = APSBOMUtils.getInstance().ChangeToJson(wNormalList, "U");
                    if (StringUtils.isNotEmpty(wJson)) {
                        String wRst = SendToSAP(wLoginUser, wJson, wOrder.OrderNo, wSFCScrapApprovalBPMID, wOrder, 2,
                                wNormalList.stream().map(p -> p.ID).distinct().collect(Collectors.toList()), 2);
                        if (wRst.contains("变更成功")) {
                            List<APSBOMItem> wCloneList = CloneTool.CloneArray(wNormalList, APSBOMItem.class);
                            // 创建物料配送单
                            wCloneList.removeIf(p -> p.AssessmentType.equals("修复旧件") &&
                                    p.ReviewComments == SFCBOMTaskReviewComments.Repair.getValue()
                                    && (p.OutsourceType == 1 || p.OutsourceType == 2));
                            if (wCloneList.size() > 0) {
                                CreatePSD_Scrap(wLoginUser, wCloneList, wSFCScrapApprovalBPMID, wErrorCode);
                            }
                        }
                    }
                }
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> APS_UpdateBOMItemListByQualityLoss(BMSEmployee wLoginUser,
                                                                     List<APSBOMItem> wDataList, int wQualityLossID,
                                                                     int wCovaType,
                                                                     List<SFCQualityLossBPMItem> wItemList) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            // 处理数据
            for (APSBOMItem wBOMItem : wDataList) {
                // 判断是否为差异项
                wBOMItem.DifferenceItem = APSBOMItemDAO.getInstance().JudgeIsDifferenceItem(wLoginUser, wBOMItem,
                        wErrorCode);

                if (wBOMItem.SourceType != APSBOMSourceType.SFCBOMTask.getValue()) {
                    if (wBOMItem.ReplaceType == 1 || wBOMItem.ReplaceType == 2) {
                        wBOMItem.AssessmentType = "常规新件";
                    }
                    if (wBOMItem.OutsourceType == 1 || wBOMItem.OutsourceType == 2) {
                        wBOMItem.AssessmentType = "修复旧件";
                    }
                    if (wBOMItem.PartChange > 0) {
                        wBOMItem.AssessmentType = "修复旧件";
                    }
                    if (wBOMItem.ReplaceType != 1 && (wBOMItem.OutsourceType == 3 || wBOMItem.OutsourceType == 4)) {
                        wBOMItem.AssessmentType = "可用旧件";
                    }
                    if (wBOMItem.ReplaceType == 1 && wBOMItem.OutsourceType == 1) {
                        wBOMItem.AssessmentType = "常规新件";
                    }
                }
            }

            OMSOrder wOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wDataList.get(0).OrderID, wErrorCode);

            // 验证台车BOM
            String wMsg = APSBOMUtils.getInstance().CheckAPSBOM(wDataList, wOrder);

            if (StringUtils.isNotEmpty(wMsg)) {

                List<BFCMessage> wBFCMessageList = new ArrayList<>();
                BFCMessage wMessage = null;
                int wShiftID = MESServer.MES_QueryShiftID(wLoginUser.CompanyID, Calendar.getInstance(),
                        APSShiftPeriod.Day, FMCShiftLevel.Day, 0);
                // 发送任务消息到人员
                wMessage = new BFCMessage();
                wMessage.Active = 0;
                wMessage.CompanyID = 0;
                wMessage.CreateTime = Calendar.getInstance();
                wMessage.EditTime = Calendar.getInstance();
                wMessage.ID = 0;
                wMessage.MessageID = 0;
                wMessage.Title = StringUtils.Format("【台车BOM】提示", BPMEventModule.StationTip.getLable());
                wMessage.MessageText = wMsg;
                wMessage.ModuleID = BPMEventModule.StationTip.getValue();
                wMessage.ResponsorID = StringUtils.parseInt(Configuration.readConfigString("bomUser", "config/config"));
                wMessage.ShiftID = wShiftID;
                wMessage.StationID = 0;
                wMessage.Type = BFCMessageType.Notify.getValue();
                wBFCMessageList.add(wMessage);

                CoreServiceImpl.getInstance().BFC_UpdateMessageList(wLoginUser, wBFCMessageList);

                // 维护SAP推送状态
                if (wQualityLossID > 0) {
                    TaskTimerUtils.AddTask("APS_UpdateBOMItemListByQualityLoss", () -> {
                        APSBOMUtils.getInstance().UpdateSFCBOMTaskSAPStatusByQualityLoss(wLoginUser, wMsg, wQualityLossID);

                    }, 1000);

                }

                // 返回提示信息
                wResult.FaultCode = wMsg;
                return wResult;
            }

            // 保存到MES系统数据库
            for (APSBOMItem wBOMItem : wDataList) {
                wBOMItem.ID = APSBOMItemDAO.getInstance().APS_UpdateBOMItem(wLoginUser, wBOMItem, wErrorCode);
                wBOMItem.ProductNo = wOrder.ProductNo;
                wBOMItem.LineName = wOrder.LineName;
                wBOMItem.CustomerCode = APSConstans.GetCRMCustomer(wBOMItem.CustomerID).CustomerCode;
                wBOMItem.PartPointName = APSConstans.GetFPCPartPointName(wBOMItem.PartPointID);
            }

            String wSendSAP = Configuration.readConfigString("isSendSAP", "config/config");

            if (wSendSAP.equals("1")) {
                // ①质量损失的数据分开发送
                List<APSBOMItem> wQualityLossList = wDataList.stream().filter(p -> p.BOMType == 9)
                        .collect(Collectors.toList());
                List<APSBOMItem> wNormalList = wDataList.stream().filter(p -> p.BOMType != 9)
                        .collect(Collectors.toList());

                if (wQualityLossList.size() > 0) {
                    // 判断是否已经有质量损失，若没有，用I创建，若有，用U更新
                    boolean wIsExist = SFCBOMTaskDAO.getInstance().IsExistQualityLoss(wLoginUser, wOrder, wErrorCode);
                    String wUpChar = "U";
                    if (!wIsExist) {
                        wUpChar = "I";
                    }

                    // ①推送台车BOM给SAP
                    String wJson = APSBOMUtils.getInstance().ChangeToJson(wQualityLossList, wUpChar);
                    if (StringUtils.isNotEmpty(wJson)) {
                        String wRst = APSBOMUtils.getInstance().SendToSAPByQualityLoss(wLoginUser, wJson, wOrder.OrderNo, wQualityLossID,
                                wOrder, 0,
                                wQualityLossList.stream().map(p -> p.ID).distinct().collect(Collectors.toList()));
                        if (wRst.contains("变更成功") || wRst.contains("保存成功")) {
                            List<APSBOMItem> wCloneList = CloneTool.CloneArray(wQualityLossList, APSBOMItem.class);
                            if (wCovaType == 1) {
                                // 线边库消耗
                                // ERP过账
                            } else {
                                // 创建物料配送单
                                wCloneList.removeIf(p -> p.AssessmentType.equals("修复旧件") &&
                                        p.ReviewComments == SFCBOMTaskReviewComments.Repair.getValue()
                                        && (p.OutsourceType == 1 || p.OutsourceType == 2));
                                if (wCloneList.size() > 0) {
                                    CreatePSDByQualityLoss(wLoginUser, wCloneList, wQualityLossID, wErrorCode);
                                }
                            }
                        }
                    }
                }

                if (wNormalList.size() > 0) {
                    // ①推送台车BOM给SAP
                    String wJson = APSBOMUtils.getInstance().ChangeToJson(wNormalList, "U");
                    if (StringUtils.isNotEmpty(wJson)) {
                        String wRst = APSBOMUtils.getInstance().SendToSAPByQualityLoss(wLoginUser, wJson, wOrder.OrderNo, wQualityLossID,
                                wOrder, 0,
                                wNormalList.stream().map(p -> p.ID).distinct().collect(Collectors.toList()));
                        if (wRst.contains("变更成功")) {
                            List<APSBOMItem> wCloneList = CloneTool.CloneArray(wNormalList, APSBOMItem.class);
                            if (wCovaType == 1) {
                                // 线边库消耗
                                // ERP过账
                            } else {
                                // 创建物料配送单
                                wCloneList.removeIf(p -> p.AssessmentType.equals("修复旧件") &&
                                        p.ReviewComments == SFCBOMTaskReviewComments.Repair.getValue()
                                        && (p.OutsourceType == 1 || p.OutsourceType == 2));
                                if (wCloneList.size() > 0) {
                                    CreatePSDByQualityLoss(wLoginUser, wCloneList, wQualityLossID, wErrorCode);
                                }
                            }
                        }
                    }
                }
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    /**
     * 创建配送单
     */
    @Override
    public synchronized void CreatePSD(BMSEmployee wLoginUser, List<APSBOMItem> wDataList,
                                       int wSFCBOMTaskID,
                                       OutResult<Integer> wErrorCode) {
        try {
            if (wSFCBOMTaskID > 0) {
                SFCBOMTask wTask = (SFCBOMTask) SFCBOMTaskDAO.getInstance().BPM_GetTaskInfo(wLoginUser, wSFCBOMTaskID,
                        "", wErrorCode);
                String wMaterialManage = Configuration.readConfigString("materialManage", "config/config");
                if (wMaterialManage.equals("1")) {
                    String testOrder = Configuration.readConfigString("testOrder", "config/config");
                    if (testOrder.equals("0")) {
                        SendToWMS(wLoginUser, wTask, wDataList);
                    } else {
                        String[] wIDs = testOrder.split(",");
                        List<Integer> wOrderIDList = new ArrayList<>();
                        for (String wIS : wIDs) {
                            wOrderIDList.add(StringUtils.parseInt(wIS));
                        }
                        if (wOrderIDList.stream().anyMatch(p -> p == wTask.OrderID)) {
                            SendToWMS(wLoginUser, wTask, wDataList);
                        }
                    }
                }
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    /**
     * 创建配送单
     */
    @Override
    public synchronized void CreatePSD_Recol(BMSEmployee wLoginUser, List<APSBOMItem> wDataList,
                                             APSTaskStep wTask,
                                             OutResult<Integer> wErrorCode) {
        try {
            String wMaterialManage = Configuration.readConfigString("materialManage", "config/config");
            if (wMaterialManage.equals("1")) {
                String testOrder = Configuration.readConfigString("testOrder", "config/config");
                if (testOrder.equals("0")) {
                    SendToWMS_Recol(wLoginUser, wTask, wDataList);
                } else {
                    String[] wIDs = testOrder.split(",");
                    List<Integer> wOrderIDList = new ArrayList<>();
                    for (String wIS : wIDs) {
                        wOrderIDList.add(StringUtils.parseInt(wIS));
                    }
                    if (wOrderIDList.stream().anyMatch(p -> p == wTask.OrderID)) {
                        SendToWMS_Recol(wLoginUser, wTask, wDataList);
                    }
                }
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    /**
     * 创建配送单
     */
    public synchronized void CreatePSD_Out(BMSEmployee wLoginUser, List<APSBOMItem> wDataList,
                                           int wSFCBOMTaskID,
                                           OutResult<Integer> wErrorCode) {
        try {
            // 获取配置，判断是否推送委外领料单
            String wOutsource = Configuration.readConfigString("OutsourcingPlan", "config/config");
            if (!wOutsource.equals("1")) {
                return;
            }

            if (wSFCBOMTaskID > 0) {
                SFCBOMTask wTask = (SFCBOMTask) SFCBOMTaskDAO.getInstance().BPM_GetTaskInfo(wLoginUser, wSFCBOMTaskID,
                        "", wErrorCode);
                String wMaterialManage = Configuration.readConfigString("materialManage", "config/config");
                if (wMaterialManage.equals("1")) {
                    String testOrder = Configuration.readConfigString("testOrder", "config/config");
                    if (testOrder.equals("0")) {
                        SendToWMS_Out(wLoginUser, wTask, wDataList);
                    } else {
                        String[] wIDs = testOrder.split(",");
                        List<Integer> wOrderIDList = new ArrayList<>();
                        for (String wIS : wIDs) {
                            wOrderIDList.add(StringUtils.parseInt(wIS));
                        }
                        if (wOrderIDList.stream().anyMatch(p -> p == wTask.OrderID)) {
                            // 读取系统配置，只生成配置的相关工位
                            String wOutLLParts = MESSystemConfigDAO.getInstance().SelectValueByKey(wLoginUser,
                                    "Out.LL.Parts", wErrorCode);
                            List<Integer> wOutLLPartsList = StringUtils.parseIntList(wOutLLParts.split(","));
                            if (wOutLLPartsList.stream().anyMatch(p -> p.intValue() == wTask.PartID)
                                    || wOutLLPartsList.size() == 0) {
                                SendToWMS_Out(wLoginUser, wTask, wDataList);
                            }
                        }
                    }
                }
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    /**
     * 创建配送单_报废审批
     */
    private synchronized void CreatePSD_Scrap(BMSEmployee wLoginUser, List<APSBOMItem> wDataList,
                                              int wSFCScrapApprovalBPMID,
                                              OutResult<Integer> wErrorCode) {
        try {
            if (wSFCScrapApprovalBPMID > 0) {
                SFCScrapApprovalBPM wTask = (SFCScrapApprovalBPM) SFCScrapApprovalBPMDAO.getInstance().BPM_GetTaskInfo(
                        wLoginUser,
                        wSFCScrapApprovalBPMID,
                        "", wErrorCode);
                String wMaterialManage = Configuration.readConfigString("materialManage", "config/config");
                if (wMaterialManage.equals("1")) {
                    String testOrder = Configuration.readConfigString("testOrder", "config/config");
                    if (testOrder.equals("0")) {
                        SendToWMS_Scrap(wLoginUser, wTask, wDataList);
                    } else {
                        String[] wIDs = testOrder.split(",");
                        List<Integer> wOrderIDList = new ArrayList<>();
                        for (String wIS : wIDs) {
                            wOrderIDList.add(StringUtils.parseInt(wIS));
                        }
                        if (wOrderIDList.stream().anyMatch(p -> p == wTask.OrderID)) {
                            SendToWMS_Scrap(wLoginUser, wTask, wDataList);
                        }
                    }
                }
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    /**
     * 创建配送单
     */
    private synchronized void CreatePSDByQualityLoss(BMSEmployee wLoginUser, List<APSBOMItem> wDataList,
                                                     int wQauiltyLossID,
                                                     OutResult<Integer> wErrorCode) {
        try {
            if (wQauiltyLossID > 0) {
                SFCQualityLossBPM wTask = (SFCQualityLossBPM) SFCQualityLossBPMDAO.getInstance().BPM_GetTaskInfo(
                        wLoginUser,
                        wQauiltyLossID,
                        "", wErrorCode);
                String wMaterialManage = Configuration.readConfigString("materialManage", "config/config");
                if (wMaterialManage.equals("1")) {
                    String testOrder = Configuration.readConfigString("testOrder", "config/config");
                    if (testOrder.equals("0")) {
                        SendToWMSByQualityLoss(wLoginUser, wTask, wDataList);
                    } else {
                        String[] wIDs = testOrder.split(",");
                        List<Integer> wOrderIDList = new ArrayList<>();
                        for (String wIS : wIDs) {
                            wOrderIDList.add(StringUtils.parseInt(wIS));
                        }
                        if (wOrderIDList.stream().anyMatch(p -> p == wTask.OrderID)) {
                            SendToWMSByQualityLoss(wLoginUser, wTask, wDataList);
                        }
                    }
                }
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    /**
     * 创建配送单
     */
    private void SendToWMS(BMSEmployee wLoginUser, SFCBOMTask wTask, List<APSBOMItem> wItemList) {
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            boolean wOutsourcingPlan = Configuration.readConfigString("OutsourcingPlan", "config/config").equals(
                    "1");
            boolean wIsSendRecoilMaterial = Configuration.readConfigString("IsSendRecoilMaterial", "config/config")
                    .equals(
                            "1");
            //是否拆分客供料
            boolean wIsSplitCustomerMaterial = MESSystemConfigDAO.getInstance().SelectValueByKey(wLoginUser,
                    "wms.split.customer.demand", wErrorCode).equals("1");

            Map<Integer, Integer> wMaterialTypeMap = MRPMaterialPlanDAO.getInstance().GetMaterialTypeMap(wLoginUser,
                    wItemList.stream().map(p -> p.MaterialID).distinct().collect(Collectors.toList()), wErrorCode);
            if (!wOutsourcingPlan) {
                // 委外偶修、委外必须不推送
                wItemList.removeIf(p -> p.ReplaceType == 0 && p.OutsourceType == 2);
                if (wItemList.size() <= 0) {
                    return;
                }
            }

            if (!wIsSendRecoilMaterial) {
                // 反冲不推送
                List<Integer> wFCList = new ArrayList<>();
                for (int wMaterialID : wMaterialTypeMap.keySet()) {
                    int wType = wMaterialTypeMap.get(wMaterialID);
                    if (wType == MSSMaterialType.RecoilMaterial.getValue()) {
                        wFCList.add(wMaterialID);
                    }
                }

                //反冲领料需求拆分
                List<APSBOMItem> wRecoilList = wItemList.stream().filter(p -> wFCList.stream().anyMatch(q -> q == p.MaterialID)).collect(Collectors.toList());
                SendToWMS_Recoil(wLoginUser, wTask, wRecoilList);

                wItemList.removeIf(p -> wFCList.stream().anyMatch(q -> q == p.MaterialID));
                if (wItemList.size() <= 0) {
                    return;
                }
            }

            //拆分客供料
            if (wIsSplitCustomerMaterial) {
                List<APSBOMItem> wCustomerMaterialList = wItemList.stream().filter(p -> p.CustomerMaterial == 1).collect(Collectors.toList());
                SendToWMS_Customer(wLoginUser, wTask, wCustomerMaterialList);

                wItemList.removeIf(p -> p.CustomerMaterial == 1);
                if (wItemList.size() <= 0) {
                    return;
                }
            }

            Calendar wBaseTime = Calendar.getInstance();
            wBaseTime.set(2000, 0, 1, 0, 0, 0);

            String wCode = WMSPickDemandDAO.getInstance().GetNewCode(wLoginUser, wErrorCode);
            Calendar wTime = Calendar.getInstance();

            Calendar expectTime1 = Calendar.getInstance();
            expectTime1.set(wTime.get(Calendar.YEAR), wTime.get(Calendar.MONTH), wTime.get(Calendar.DATE), 0, 0, 0);

            Calendar expectTime2 = Calendar.getInstance();
            expectTime2.set(wTime.get(Calendar.YEAR), wTime.get(Calendar.MONTH), wTime.get(Calendar.DATE), 12, 0, 0);

            String monitorNo = "";
            String monitor = "";
            BMSEmployee wUser = WMSPickDemandDAO.getInstance().GetMonitorByPart(wLoginUser, wTask.PartID, wErrorCode);
            if (StringUtils.isNotEmpty(wUser.LoginID)) {
                monitorNo = wUser.LoginID;
                monitor = wUser.Name;
            }

            OMSOrder wOMSOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wTask.OrderID, wErrorCode);

            // 获取物料最小包装字典
            List<Integer> wMaterialIDList = wItemList.stream().map(p -> p.MaterialID).distinct()
                    .collect(Collectors.toList());
            Map<Integer, Double> wMaterialPackMap = MRPMaterialPlanDAO.getInstance().GetMaterialPackMap(wLoginUser,
                    wMaterialIDList, wErrorCode);

            WMSPickDemand wWMSPickDemand = new WMSPickDemand(0, "1900",
                    String.valueOf(WMSOrderType.LineOrder.getValue()), wCode, expectTime1, expectTime2, monitorNo,
                    monitor, wTask.ProductID, wTask.ProductNo, wTask.LineID, wTask.LineName, wTask.CustomerID,
                    APSConstans.GetCRMCustomer(wTask.CustomerID).CustomerName,
                    APSConstans.GetCRMCustomer(wTask.CustomerID).CustomerCode, wTask.OrderID, wTask.PartNo,
                    wTask.PartID, APSConstans.GetFPCPartName(wTask.PartID), APSConstans.GetFPCPart(wTask.PartID).Code,
                    "", "", wBaseTime, "", "", wBaseTime, 1, wLoginUser.ID, wLoginUser.Name, Calendar.getInstance(),
                    wOMSOrder.OrderNo, wBaseTime);
            wWMSPickDemand.SourceType = WMSPickDemandSourceType.OHJ.getValue();
            wWMSPickDemand.SourceID = wItemList.get(0).NewSourceID;
            wWMSPickDemand.SourceCode = wItemList.get(0).NewSourceCode;
            wWMSPickDemand.ReceiveID = wTask.UpFlowID;
            int wDemandID = WMSPickDemandDAO.getInstance().Update(wLoginUser, wWMSPickDemand, wErrorCode);
            if (wDemandID <= 0) {
                return;
            }
            // ④创建领料需求单明细

            int wIndex = 1;
            for (APSBOMItem wAPSBOMItem : wItemList) {

                double wFQTY = wAPSBOMItem.Number;
                int wMaterialType = 0;
                if (wMaterialTypeMap.containsKey(wAPSBOMItem.MaterialID)) {
                    wMaterialType = wMaterialTypeMap.get(wAPSBOMItem.MaterialID);
                }
                // 根据最小包装计算需求
                if (wMaterialPackMap.containsKey(wAPSBOMItem.MaterialID)
                        && wMaterialType == MSSMaterialType.RecoilMaterial.getValue() && wIsSendRecoilMaterial) {
                    double wMinPack = wMaterialPackMap.get(wAPSBOMItem.MaterialID);
                    if (wMinPack > 0) {
                        int wAreaID = APSUtils.getInstance().GetAreaID(wAPSBOMItem.PartID);
                        wFQTY = WMSServiceImpl.getInstance().WMS_GetRealLLNumber(wLoginUser, wMinPack,
                                wAPSBOMItem.MaterialID, wAPSBOMItem.Number, wAreaID, wErrorCode).Result;
                    }
                }

                WMSPickDemandItem wWMSPickDemandItem = new WMSPickDemandItem(0, wDemandID, wAPSBOMItem.MaterialID,
                        wAPSBOMItem.MaterialNo, wAPSBOMItem.MaterialName, wAPSBOMItem.Number, wOMSOrder.OrderNo,
                        wTask.PartPointID, APSConstans.GetFPCPartPoint(wTask.PartPointID).Code.replace("PS-", ""),
                        APSConstans.GetFPCPartPointName(wTask.PartPointID), String.valueOf(wIndex), "",
                        wAPSBOMItem.ReplaceType, SFCReplaceType.getEnumType(wAPSBOMItem.ReplaceType).getLable(),
                        wAPSBOMItem.OutsourceType, SFCOutSourceType.getEnumType(wAPSBOMItem.OutsourceType).getLable(),
                        wAPSBOMItem.AssessmentType, "", wBaseTime, wWMSPickDemand.PartID, 1, wAPSBOMItem.Number,
                        wAPSBOMItem.OrderNum);
                wWMSPickDemandItem.FQTY = wFQTY;

                wWMSPickDemandItem.IsOriDis = wAPSBOMItem.OriginalType == 1 ? "是" : "否";

                int wItemID = WMSPickDemandItemDAO.getInstance().Update(wLoginUser, wWMSPickDemandItem, wErrorCode);
                if (wItemID > 0 && wWMSPickDemandItem.FQTY < wAPSBOMItem.Number) {
                    WMSServiceImpl.getInstance().WMS_RecoilMaterialUse(wLoginUser, wItemID);
                }
                wIndex++;
            }

            // ①手动推送
            String autoSendWMS = Configuration.readConfigString("autoSendWMS", "config/config");
            if (autoSendWMS.equals("1")) {
                WMSServiceImpl.getInstance().WMS_ManualPush(wLoginUser, wDemandID);
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    /**
     * 推送反冲领料需求
     */
    private void SendToWMS_Recoil(BMSEmployee wLoginUser, SFCBOMTask wTask, List<APSBOMItem> wItemList) {
        try {
            OutResult<Integer> wErrorCode = new OutResult<Integer>(0);
            // ①读取配置，判断是否需要拆分反冲需求
            String wSplit = MESSystemConfigDAO.getInstance().SelectValueByKey(BaseDAO.SysAdmin,
                    "wms.split.recoil.demand", wErrorCode);
            if (StringUtils.isEmpty(wSplit)) {
                logger.info("未配置是否需要拆分反冲需求!");
                return;
            }

            Calendar wBaseTime = Calendar.getInstance();
            wBaseTime.set(2000, 0, 1, 0, 0, 0);

            String wCode = WMSPickDemandDAO.getInstance().GetNewCode(wLoginUser, wErrorCode);
            Calendar wTime = Calendar.getInstance();

            Calendar expectTime1 = Calendar.getInstance();
            expectTime1.set(wTime.get(Calendar.YEAR), wTime.get(Calendar.MONTH), wTime.get(Calendar.DATE), 0, 0, 0);

            Calendar expectTime2 = Calendar.getInstance();
            expectTime2.set(wTime.get(Calendar.YEAR), wTime.get(Calendar.MONTH), wTime.get(Calendar.DATE), 12, 0, 0);

            String monitorNo = "";
            String monitor = "";
            BMSEmployee wUser = WMSPickDemandDAO.getInstance().GetMonitorByPart(wLoginUser, wTask.PartID, wErrorCode);
            if (StringUtils.isNotEmpty(wUser.LoginID)) {
                monitorNo = wUser.LoginID;
                monitor = wUser.Name;
            }

            OMSOrder wOMSOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wTask.OrderID, wErrorCode);

            WMSPickDemand wWMSPickDemand = new WMSPickDemand(0, "1900",
                    String.valueOf(WMSOrderType.RecoilLL.getValue()), wCode, expectTime1, expectTime2, monitorNo,
                    monitor, wTask.ProductID, wTask.ProductNo, wTask.LineID, wTask.LineName, wTask.CustomerID,
                    APSConstans.GetCRMCustomer(wTask.CustomerID).CustomerName,
                    APSConstans.GetCRMCustomer(wTask.CustomerID).CustomerCode, wTask.OrderID, wTask.PartNo,
                    wTask.PartID, APSConstans.GetFPCPartName(wTask.PartID), APSConstans.GetFPCPart(wTask.PartID).Code,
                    "", "", wBaseTime, "", "", wBaseTime, 1, wLoginUser.ID, wLoginUser.Name, Calendar.getInstance(),
                    wOMSOrder.OrderNo, wBaseTime);
            wWMSPickDemand.SourceType = WMSPickDemandSourceType.OHJ.getValue();
            wWMSPickDemand.SourceID = wItemList.get(0).NewSourceID;
            wWMSPickDemand.SourceCode = wItemList.get(0).NewSourceCode;
            wWMSPickDemand.ReceiveID = wTask.UpFlowID;
            int wDemandID = WMSPickDemandDAO.getInstance().Update(wLoginUser, wWMSPickDemand, wErrorCode);
            if (wDemandID <= 0) {
                return;
            }
            // ④创建领料需求单明细
            int wIndex = 1;
            for (APSBOMItem wAPSBOMItem : wItemList) {
                double wFQTY = wAPSBOMItem.Number;
                WMSPickDemandItem wWMSPickDemandItem = new WMSPickDemandItem(0, wDemandID, wAPSBOMItem.MaterialID,
                        wAPSBOMItem.MaterialNo, wAPSBOMItem.MaterialName, wAPSBOMItem.Number, wOMSOrder.OrderNo,
                        wTask.PartPointID, APSConstans.GetFPCPartPoint(wTask.PartPointID).Code.replace("PS-", ""),
                        APSConstans.GetFPCPartPointName(wTask.PartPointID), String.valueOf(wIndex), "",
                        wAPSBOMItem.ReplaceType, SFCReplaceType.getEnumType(wAPSBOMItem.ReplaceType).getLable(),
                        wAPSBOMItem.OutsourceType, SFCOutSourceType.getEnumType(wAPSBOMItem.OutsourceType).getLable(),
                        wAPSBOMItem.AssessmentType, "", wBaseTime, wWMSPickDemand.PartID, 1, wAPSBOMItem.Number,
                        wAPSBOMItem.OrderNum);
                wWMSPickDemandItem.FQTY = wFQTY;
                wWMSPickDemandItem.IsOriDis = wAPSBOMItem.OriginalType == 1 ? "是" : "否";
                WMSPickDemandItemDAO.getInstance().Update(wLoginUser, wWMSPickDemandItem, wErrorCode);
                wIndex++;
            }

            // ①手动推送
            String autoSendWMS = Configuration.readConfigString("autoSendWMS", "config/config");
            if (autoSendWMS.equals("1")) {
                WMSServiceImpl.getInstance().WMS_ManualPush(wLoginUser, wDemandID);
            }
        } catch (Exception ex) {
            logger.error("SendToWMS_Recoil", ex);
        }
    }

    /**
     * 推送客供领料需求
     */
    private void SendToWMS_Customer(BMSEmployee wLoginUser, SFCBOMTask wTask, List<APSBOMItem> wItemList) {
        try {
            OutResult<Integer> wErrorCode = new OutResult<Integer>(0);
            // ①读取配置，判断是否需要拆分客供需求
            String wSplit = MESSystemConfigDAO.getInstance().SelectValueByKey(BaseDAO.SysAdmin,
                    "wms.split.customer.demand", wErrorCode);
            if (StringUtils.isEmpty(wSplit)) {
                logger.info("未配置是否需要拆分客供需求!");
                return;
            }

            Calendar wBaseTime = Calendar.getInstance();
            wBaseTime.set(2000, 0, 1, 0, 0, 0);

            String wCode = WMSPickDemandDAO.getInstance().GetNewCode(wLoginUser, wErrorCode);
            Calendar wTime = Calendar.getInstance();

            Calendar expectTime1 = Calendar.getInstance();
            expectTime1.set(wTime.get(Calendar.YEAR), wTime.get(Calendar.MONTH), wTime.get(Calendar.DATE), 0, 0, 0);

            Calendar expectTime2 = Calendar.getInstance();
            expectTime2.set(wTime.get(Calendar.YEAR), wTime.get(Calendar.MONTH), wTime.get(Calendar.DATE), 12, 0, 0);

            String monitorNo = "";
            String monitor = "";
            BMSEmployee wUser = WMSPickDemandDAO.getInstance().GetMonitorByPart(wLoginUser, wTask.PartID, wErrorCode);
            if (StringUtils.isNotEmpty(wUser.LoginID)) {
                monitorNo = wUser.LoginID;
                monitor = wUser.Name;
            }

            OMSOrder wOMSOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wTask.OrderID, wErrorCode);

            WMSPickDemand wWMSPickDemand = new WMSPickDemand(0, "1900",
                    String.valueOf(WMSOrderType.CustomerLL.getValue()), wCode, expectTime1, expectTime2, monitorNo,
                    monitor, wTask.ProductID, wTask.ProductNo, wTask.LineID, wTask.LineName, wTask.CustomerID,
                    APSConstans.GetCRMCustomer(wTask.CustomerID).CustomerName,
                    APSConstans.GetCRMCustomer(wTask.CustomerID).CustomerCode, wTask.OrderID, wTask.PartNo,
                    wTask.PartID, APSConstans.GetFPCPartName(wTask.PartID), APSConstans.GetFPCPart(wTask.PartID).Code,
                    "", "", wBaseTime, "", "", wBaseTime, 1, wLoginUser.ID, wLoginUser.Name, Calendar.getInstance(),
                    wOMSOrder.OrderNo, wBaseTime);
            wWMSPickDemand.SourceType = WMSPickDemandSourceType.OHJ.getValue();
            wWMSPickDemand.SourceID = wItemList.get(0).NewSourceID;
            wWMSPickDemand.SourceCode = wItemList.get(0).NewSourceCode;
            wWMSPickDemand.ReceiveID = wTask.UpFlowID;
            int wDemandID = WMSPickDemandDAO.getInstance().Update(wLoginUser, wWMSPickDemand, wErrorCode);
            if (wDemandID <= 0) {
                return;
            }
            // ④创建领料需求单明细
            int wIndex = 1;
            for (APSBOMItem wAPSBOMItem : wItemList) {
                double wFQTY = wAPSBOMItem.Number;
                WMSPickDemandItem wWMSPickDemandItem = new WMSPickDemandItem(0, wDemandID, wAPSBOMItem.MaterialID,
                        wAPSBOMItem.MaterialNo, wAPSBOMItem.MaterialName, wAPSBOMItem.Number, wOMSOrder.OrderNo,
                        wTask.PartPointID, APSConstans.GetFPCPartPoint(wTask.PartPointID).Code.replace("PS-", ""),
                        APSConstans.GetFPCPartPointName(wTask.PartPointID), String.valueOf(wIndex), "",
                        wAPSBOMItem.ReplaceType, SFCReplaceType.getEnumType(wAPSBOMItem.ReplaceType).getLable(),
                        wAPSBOMItem.OutsourceType, SFCOutSourceType.getEnumType(wAPSBOMItem.OutsourceType).getLable(),
                        wAPSBOMItem.AssessmentType, "", wBaseTime, wWMSPickDemand.PartID, 1, wAPSBOMItem.Number,
                        wAPSBOMItem.OrderNum);
                wWMSPickDemandItem.FQTY = wFQTY;
                wWMSPickDemandItem.IsOriDis = wAPSBOMItem.OriginalType == 1 ? "是" : "否";
                WMSPickDemandItemDAO.getInstance().Update(wLoginUser, wWMSPickDemandItem, wErrorCode);
                wIndex++;
            }

            // ①手动推送
            String autoSendWMS = Configuration.readConfigString("autoSendWMS", "config/config");
            if (autoSendWMS.equals("1")) {
                WMSServiceImpl.getInstance().WMS_ManualPush(wLoginUser, wDemandID);
            }
        } catch (Exception ex) {
            logger.error("SendToWMS_Recoil", ex);
        }
    }

    /**
     * 推送客供领料需求
     */
    private void SendToWMS_Customer(BMSEmployee wLoginUser, APSBomBPM wTask, List<APSBOMItem> wItemList) {
        try {
            OutResult<Integer> wErrorCode = new OutResult<Integer>(0);
            // ①读取配置，判断是否需要拆分客供需求
            String wSplit = MESSystemConfigDAO.getInstance().SelectValueByKey(BaseDAO.SysAdmin,
                    "wms.split.customer.demand", wErrorCode);
            if (StringUtils.isEmpty(wSplit)) {
                logger.info("未配置是否需要拆分客供需求!");
                return;
            }

            Calendar wBaseTime = Calendar.getInstance();
            wBaseTime.set(2000, 0, 1, 0, 0, 0);

            String wCode = WMSPickDemandDAO.getInstance().GetNewCode(wLoginUser, wErrorCode);
            Calendar wTime = Calendar.getInstance();

            Calendar expectTime1 = Calendar.getInstance();
            expectTime1.set(wTime.get(Calendar.YEAR), wTime.get(Calendar.MONTH), wTime.get(Calendar.DATE), 0, 0, 0);

            Calendar expectTime2 = Calendar.getInstance();
            expectTime2.set(wTime.get(Calendar.YEAR), wTime.get(Calendar.MONTH), wTime.get(Calendar.DATE), 12, 0, 0);

            String monitorNo = "";
            String monitor = "";
            BMSEmployee wUser = WMSPickDemandDAO.getInstance().GetMonitorByPart(wLoginUser, wItemList.get(0).PartID, wErrorCode);
            if (StringUtils.isNotEmpty(wUser.LoginID)) {
                monitorNo = wUser.LoginID;
                monitor = wUser.Name;
            }

            OMSOrder wOMSOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wTask.OrderID, wErrorCode);

            WMSPickDemand wWMSPickDemand = new WMSPickDemand(0, "1900",
                    String.valueOf(WMSOrderType.CustomerLL.getValue()), wCode, expectTime1, expectTime2, monitorNo,
                    monitor, wTask.ProductID, wTask.ProductNo, wTask.LineID, wTask.LineName, wTask.CustomerID,
                    APSConstans.GetCRMCustomer(wTask.CustomerID).CustomerName,
                    APSConstans.GetCRMCustomer(wTask.CustomerID).CustomerCode, wTask.OrderID, wTask.PartNo,
                    wItemList.get(0).PartID, APSConstans.GetFPCPartName(wItemList.get(0).PartID), APSConstans.GetFPCPart(wItemList.get(0).PartID).Code,
                    "", "", wBaseTime, "", "", wBaseTime, 1, wLoginUser.ID, wLoginUser.Name, Calendar.getInstance(),
                    wOMSOrder.OrderNo, wBaseTime);
            wWMSPickDemand.SourceType = WMSPickDemandSourceType.OHJ.getValue();
            wWMSPickDemand.SourceID = wItemList.get(0).NewSourceID;
            wWMSPickDemand.SourceCode = wItemList.get(0).NewSourceCode;
            wWMSPickDemand.ReceiveID = wTask.UpFlowID;
            int wDemandID = WMSPickDemandDAO.getInstance().Update(wLoginUser, wWMSPickDemand, wErrorCode);
            if (wDemandID <= 0) {
                return;
            }
            // ④创建领料需求单明细
            int wIndex = 1;
            for (APSBOMItem wAPSBOMItem : wItemList) {
                double wFQTY = wAPSBOMItem.Number;
                WMSPickDemandItem wWMSPickDemandItem = new WMSPickDemandItem(0, wDemandID, wAPSBOMItem.MaterialID,
                        wAPSBOMItem.MaterialNo, wAPSBOMItem.MaterialName, wAPSBOMItem.Number, wOMSOrder.OrderNo,
                        wItemList.get(0).PartPointID, APSConstans.GetFPCPartPoint(wItemList.get(0).PartPointID).Code.replace("PS-", ""),
                        APSConstans.GetFPCPartPointName(wItemList.get(0).PartPointID), String.valueOf(wIndex), "",
                        wAPSBOMItem.ReplaceType, SFCReplaceType.getEnumType(wAPSBOMItem.ReplaceType).getLable(),
                        wAPSBOMItem.OutsourceType, SFCOutSourceType.getEnumType(wAPSBOMItem.OutsourceType).getLable(),
                        wAPSBOMItem.AssessmentType, "", wBaseTime, wWMSPickDemand.PartID, 1, wAPSBOMItem.Number,
                        wAPSBOMItem.OrderNum);
                wWMSPickDemandItem.FQTY = wFQTY;
                wWMSPickDemandItem.IsOriDis = wAPSBOMItem.OriginalType == 1 ? "是" : "否";
                WMSPickDemandItemDAO.getInstance().Update(wLoginUser, wWMSPickDemandItem, wErrorCode);
                wIndex++;
            }

            // ①手动推送
            String autoSendWMS = Configuration.readConfigString("autoSendWMS", "config/config");
            if (autoSendWMS.equals("1")) {
                WMSServiceImpl.getInstance().WMS_ManualPush(wLoginUser, wDemandID);
            }
        } catch (Exception ex) {
            logger.error("SendToWMS_Recoil", ex);
        }
    }

    /**
     * 创建配送单
     */
    private void SendToWMS_Recol(BMSEmployee wLoginUser, APSTaskStep wTask, List<APSBOMItem> wItemList) {
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            if (wItemList == null || wItemList.size() <= 0) {
                logger.info("台车bom数量为0!");
                return;
            }

            Calendar wBaseTime = Calendar.getInstance();
            wBaseTime.set(2000, 0, 1, 0, 0, 0);

            String wCode = WMSPickDemandDAO.getInstance().GetNewCode(wLoginUser, wErrorCode);
            Calendar wTime = Calendar.getInstance();

            Calendar expectTime1 = Calendar.getInstance();
            expectTime1.set(wTime.get(Calendar.YEAR), wTime.get(Calendar.MONTH), wTime.get(Calendar.DATE), 0, 0, 0);

            Calendar expectTime2 = Calendar.getInstance();
            expectTime2.set(wTime.get(Calendar.YEAR), wTime.get(Calendar.MONTH), wTime.get(Calendar.DATE), 12, 0, 0);

            String monitorNo = "";
            String monitor = "";
            BMSEmployee wUser = WMSPickDemandDAO.getInstance().GetMonitorByPart(wLoginUser, wItemList.get(0).PartID, wErrorCode);
            if (StringUtils.isNotEmpty(wUser.LoginID)) {
                monitorNo = wUser.LoginID;
                monitor = wUser.Name;
            }

            OMSOrder wOMSOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wItemList.get(0).OrderID, wErrorCode);

            // 获取物料最小包装字典
            List<Integer> wMaterialIDList = wItemList.stream().map(p -> p.MaterialID).distinct()
                    .collect(Collectors.toList());
            Map<Integer, Double> wMaterialPackMap = MRPMaterialPlanDAO.getInstance().GetMaterialPackMap(wLoginUser,
                    wMaterialIDList, wErrorCode);

            WMSPickDemand wWMSPickDemand = new WMSPickDemand(0, "1900",
                    String.valueOf(WMSOrderType.RecoilLL.getValue()), wCode, expectTime1, expectTime2, monitorNo,
                    monitor, wTask.ProductID, wTask.ProductNo, wTask.LineID, wTask.LineName, wTask.CustomerID,
                    APSConstans.GetCRMCustomer(wTask.CustomerID).CustomerName,
                    APSConstans.GetCRMCustomer(wTask.CustomerID).CustomerCode, wTask.OrderID, wTask.PartNo,
                    wTask.PartID, APSConstans.GetFPCPartName(wTask.PartID), APSConstans.GetFPCPart(wTask.PartID).Code,
                    "", "", wBaseTime, "", "", wBaseTime, 1, wLoginUser.ID, wLoginUser.Name, Calendar.getInstance(),
                    wOMSOrder.OrderNo, wBaseTime);
            wWMSPickDemand.SourceType = WMSPickDemandSourceType.Plan.getValue();
            wWMSPickDemand.SourceID = wItemList.get(0).NewSourceID;
            wWMSPickDemand.SourceCode = wItemList.get(0).NewSourceCode;
            wWMSPickDemand.ReceiveID = wLoginUser.ID;
            int wDemandID = WMSPickDemandDAO.getInstance().Update(wLoginUser, wWMSPickDemand, wErrorCode);
            if (wDemandID <= 0) {
                return;
            }
            // ④创建领料需求单明细
            int wIndex = 1;
            for (APSBOMItem wAPSBOMItem : wItemList) {
                double wFQTY = wAPSBOMItem.Number;
                WMSPickDemandItem wWMSPickDemandItem = new WMSPickDemandItem(0, wDemandID, wAPSBOMItem.MaterialID,
                        wAPSBOMItem.MaterialNo, wAPSBOMItem.MaterialName, wAPSBOMItem.Number, wOMSOrder.OrderNo,
                        wTask.StepID, APSConstans.GetFPCPartPoint(wTask.StepID).Code.replace("PS-", ""),
                        APSConstans.GetFPCPartPointName(wTask.StepID), String.valueOf(wIndex), "",
                        wAPSBOMItem.ReplaceType, SFCReplaceType.getEnumType(wAPSBOMItem.ReplaceType).getLable(),
                        wAPSBOMItem.OutsourceType, SFCOutSourceType.getEnumType(wAPSBOMItem.OutsourceType).getLable(),
                        wAPSBOMItem.AssessmentType, "", wBaseTime, wWMSPickDemand.PartID, 1, wAPSBOMItem.Number,
                        wAPSBOMItem.OrderNum);
                wWMSPickDemandItem.FQTY = wFQTY;
                wWMSPickDemandItem.IsOriDis = wAPSBOMItem.OriginalType == 1 ? "是" : "否";

                int wItemID = WMSPickDemandItemDAO.getInstance().Update(wLoginUser, wWMSPickDemandItem, wErrorCode);
                if (wItemID > 0 && wWMSPickDemandItem.FQTY < wAPSBOMItem.Number) {
                    WMSServiceImpl.getInstance().WMS_RecoilMaterialUse(wLoginUser, wItemID);
                }
                wIndex++;
            }

            // ①手动推送
            String autoSendWMS = Configuration.readConfigString("autoSendWMS", "config/config");
            if (autoSendWMS.equals("1")) {
                WMSServiceImpl.getInstance().WMS_ManualPush(wLoginUser, wDemandID);
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    /**
     * 创建配送单（委外领料）
     */
    private void SendToWMS_Out(BMSEmployee wLoginUser, SFCBOMTask wTask, List<APSBOMItem> wItemList) {
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            boolean wOutsourcingPlan = Configuration.readConfigString("OutsourcingPlan", "config/config").equals(
                    "1");
            boolean wIsSendRecoilMaterial = Configuration.readConfigString("IsSendRecoilMaterial", "config/config")
                    .equals(
                            "1");
            //是否拆分客供料
            boolean wIsSplitCustomerMaterial = MESSystemConfigDAO.getInstance().SelectValueByKey(wLoginUser,
                    "wms.split.customer.demand", wErrorCode).equals("1");

            Map<Integer, Integer> wMaterialTypeMap = MRPMaterialPlanDAO.getInstance().GetMaterialTypeMap(wLoginUser,
                    wItemList.stream().map(p -> p.MaterialID).distinct().collect(Collectors.toList()), wErrorCode);
            if (!wOutsourcingPlan) {
                // 委外偶修、委外必修不推送
                wItemList.removeIf(p -> p.ReplaceType == 0 && (p.OutsourceType == 1 || p.OutsourceType == 2));
                if (wItemList.size() <= 0) {
                    return;
                }
            }

            if (!wIsSendRecoilMaterial) {
                // 反冲不推送
                List<Integer> wFCList = new ArrayList<>();
                for (int wMaterialID : wMaterialTypeMap.keySet()) {
                    int wType = wMaterialTypeMap.get(wMaterialID);
                    if (wType == MSSMaterialType.RecoilMaterial.getValue()) {
                        wFCList.add(wMaterialID);
                    }
                }

                //拆分反冲领料需求
                List<APSBOMItem> wRecoilList = wItemList.stream().filter(p -> wFCList.stream().anyMatch(q -> q == p.MaterialID)).collect(Collectors.toList());
                SendToWMS_Recoil(wLoginUser, wTask, wRecoilList);

                wItemList.removeIf(p -> wFCList.stream().anyMatch(q -> q == p.MaterialID));
                if (wItemList.size() <= 0) {
                    return;
                }
            }

            //拆分客供料
            if (wIsSplitCustomerMaterial) {
                List<APSBOMItem> wCustomerMaterialList = wItemList.stream().filter(p -> p.CustomerMaterial == 1).collect(Collectors.toList());
                SendToWMS_Customer(wLoginUser, wTask, wCustomerMaterialList);

                wItemList.removeIf(p -> p.CustomerMaterial == 1);
                if (wItemList.size() <= 0) {
                    return;
                }
            }

            Calendar wBaseTime = Calendar.getInstance();
            wBaseTime.set(2000, 0, 1, 0, 0, 0);

            String wCode = WMSPickDemandDAO.getInstance().GetNewCode(wLoginUser, wErrorCode);
            Calendar wTime = Calendar.getInstance();

            Calendar expectTime1 = Calendar.getInstance();
            expectTime1.set(wTime.get(Calendar.YEAR), wTime.get(Calendar.MONTH), wTime.get(Calendar.DATE), 0, 0, 0);

            Calendar expectTime2 = Calendar.getInstance();
            expectTime2.set(wTime.get(Calendar.YEAR), wTime.get(Calendar.MONTH), wTime.get(Calendar.DATE), 12, 0, 0);

            String monitorNo = "";
            String monitor = "";
            BMSEmployee wUser = WMSPickDemandDAO.getInstance().GetMonitorByPart(wLoginUser, wTask.PartID, wErrorCode);
            if (StringUtils.isNotEmpty(wUser.LoginID)) {
                monitorNo = wUser.LoginID;
                monitor = wUser.Name;
            }

            OMSOrder wOMSOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wTask.OrderID, wErrorCode);

            // 获取物料最小包装字典
            List<Integer> wMaterialIDList = wItemList.stream().map(p -> p.MaterialID).distinct()
                    .collect(Collectors.toList());
            Map<Integer, Double> wMaterialPackMap = MRPMaterialPlanDAO.getInstance().GetMaterialPackMap(wLoginUser,
                    wMaterialIDList, wErrorCode);

            WMSPickDemand wWMSPickDemand = new WMSPickDemand(0, "1900",
                    String.valueOf(WMSOrderType.OutLL.getValue()), wCode, expectTime1, expectTime2, monitorNo,
                    monitor, wTask.ProductID, wTask.ProductNo, wTask.LineID, wTask.LineName, wTask.CustomerID,
                    APSConstans.GetCRMCustomer(wTask.CustomerID).CustomerName,
                    APSConstans.GetCRMCustomer(wTask.CustomerID).CustomerCode, wTask.OrderID, wTask.PartNo,
                    wTask.PartID, APSConstans.GetFPCPartName(wTask.PartID), APSConstans.GetFPCPart(wTask.PartID).Code,
                    "", "", wBaseTime, "", "", wBaseTime, 1, wLoginUser.ID, wLoginUser.Name, Calendar.getInstance(),
                    wOMSOrder.OrderNo, wBaseTime);
            wWMSPickDemand.SourceType = WMSPickDemandSourceType.OHJ_Out.getValue();
            wWMSPickDemand.SourceID = wItemList.get(0).NewSourceID;
            wWMSPickDemand.SourceCode = wItemList.get(0).NewSourceCode;
            wWMSPickDemand.ReceiveID = wTask.UpFlowID;
            int wDemandID = WMSPickDemandDAO.getInstance().Update(wLoginUser, wWMSPickDemand, wErrorCode);
            if (wDemandID <= 0) {
                return;
            }
            // ④创建领料需求单明细

            int wIndex = 1;
            for (APSBOMItem wAPSBOMItem : wItemList) {

                double wFQTY = wAPSBOMItem.Number;
                int wMaterialType = 0;
                if (wMaterialTypeMap.containsKey(wAPSBOMItem.MaterialID)) {
                    wMaterialType = wMaterialTypeMap.get(wAPSBOMItem.MaterialID);
                }
                // 根据最小包装计算需求
                if (wMaterialPackMap.containsKey(wAPSBOMItem.MaterialID)
                        && wMaterialType == MSSMaterialType.RecoilMaterial.getValue() && wIsSendRecoilMaterial) {
                    double wMinPack = wMaterialPackMap.get(wAPSBOMItem.MaterialID);
                    if (wMinPack > 0) {
                        int wAreaID = APSUtils.getInstance().GetAreaID(wAPSBOMItem.PartID);
                        wFQTY = WMSServiceImpl.getInstance().WMS_GetRealLLNumber(wLoginUser, wMinPack,
                                wAPSBOMItem.MaterialID, wAPSBOMItem.Number, wAreaID, wErrorCode).Result;
                    }
                }

                WMSPickDemandItem wWMSPickDemandItem = new WMSPickDemandItem(0, wDemandID, wAPSBOMItem.MaterialID,
                        wAPSBOMItem.MaterialNo, wAPSBOMItem.MaterialName, wAPSBOMItem.Number, wOMSOrder.OrderNo,
                        wTask.PartPointID, APSConstans.GetFPCPartPoint(wTask.PartPointID).Code.replace("PS-", ""),
                        APSConstans.GetFPCPartPointName(wTask.PartPointID), String.valueOf(wIndex), "",
                        wAPSBOMItem.ReplaceType, SFCReplaceType.getEnumType(wAPSBOMItem.ReplaceType).getLable(),
                        wAPSBOMItem.OutsourceType, SFCOutSourceType.getEnumType(wAPSBOMItem.OutsourceType).getLable(),
                        wAPSBOMItem.AssessmentType, "", wBaseTime, wWMSPickDemand.PartID, 1, wAPSBOMItem.Number,
                        wAPSBOMItem.OrderNum);
                wWMSPickDemandItem.FQTY = wFQTY;
                wWMSPickDemandItem.IsOriDis = wAPSBOMItem.OriginalType == 1 ? "是" : "否";

                int wItemID = WMSPickDemandItemDAO.getInstance().Update(wLoginUser, wWMSPickDemandItem, wErrorCode);
                if (wItemID > 0 && wWMSPickDemandItem.FQTY < wAPSBOMItem.Number) {
                    WMSServiceImpl.getInstance().WMS_RecoilMaterialUse(wLoginUser, wItemID);
                }
                wIndex++;
            }

            // ①手动推送
            String autoSendWMS = Configuration.readConfigString("autoSendWMS", "config/config");
            if (autoSendWMS.equals("1")) {
                WMSServiceImpl.getInstance().WMS_ManualPush(wLoginUser, wDemandID);
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    /**
     * 创建配送单
     */
    private void SendToWMS_Scrap(BMSEmployee wLoginUser, SFCScrapApprovalBPM wTask, List<APSBOMItem> wItemList) {
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            boolean wOutsourcingPlan = Configuration.readConfigString("OutsourcingPlan", "config/config").equals(
                    "1");
            boolean wIsSendRecoilMaterial = Configuration.readConfigString("IsSendRecoilMaterial", "config/config")
                    .equals(
                            "1");
            Map<Integer, Integer> wMaterialTypeMap = MRPMaterialPlanDAO.getInstance().GetMaterialTypeMap(wLoginUser,
                    wItemList.stream().map(p -> p.MaterialID).distinct().collect(Collectors.toList()), wErrorCode);
            if (!wOutsourcingPlan) {
                // 委外偶修、委外必须不推送
                wItemList.removeIf(p -> p.ReplaceType == 0 && p.OutsourceType == 2);
                if (wItemList.size() <= 0) {
                    return;
                }
            }

            if (!wIsSendRecoilMaterial) {
                // 反冲不推送
                List<Integer> wFCList = new ArrayList<>();
                for (int wMaterialID : wMaterialTypeMap.keySet()) {
                    int wType = wMaterialTypeMap.get(wMaterialID);
                    if (wType == MSSMaterialType.RecoilMaterial.getValue()) {
                        wFCList.add(wMaterialID);
                    }
                }
                wItemList.removeIf(p -> wFCList.stream().anyMatch(q -> q == p.MaterialID));
                if (wItemList.size() <= 0) {
                    return;
                }
            }

            Calendar wBaseTime = Calendar.getInstance();
            wBaseTime.set(2000, 0, 1, 0, 0, 0);

            String wCode = WMSPickDemandDAO.getInstance().GetNewCode(wLoginUser, wErrorCode);
            Calendar wTime = Calendar.getInstance();

            Calendar expectTime1 = Calendar.getInstance();
            expectTime1.set(wTime.get(Calendar.YEAR), wTime.get(Calendar.MONTH), wTime.get(Calendar.DATE), 0, 0, 0);

            Calendar expectTime2 = Calendar.getInstance();
            expectTime2.set(wTime.get(Calendar.YEAR), wTime.get(Calendar.MONTH), wTime.get(Calendar.DATE), 12, 0, 0);

            String monitorNo = "";
            String monitor = "";
            BMSEmployee wUser = WMSPickDemandDAO.getInstance().GetMonitorByPart(wLoginUser, wTask.PartID, wErrorCode);
            if (StringUtils.isNotEmpty(wUser.LoginID)) {
                monitorNo = wUser.LoginID;
                monitor = wUser.Name;
            }

            OMSOrder wOMSOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wTask.OrderID, wErrorCode);

            // 获取物料最小包装字典
            List<Integer> wMaterialIDList = wItemList.stream().map(p -> p.MaterialID).distinct()
                    .collect(Collectors.toList());
            Map<Integer, Double> wMaterialPackMap = MRPMaterialPlanDAO.getInstance().GetMaterialPackMap(wLoginUser,
                    wMaterialIDList, wErrorCode);

            WMSPickDemand wWMSPickDemand = new WMSPickDemand(0, "1900",
                    String.valueOf(WMSOrderType.LineOrder.getValue()), wCode, expectTime1, expectTime2, monitorNo,
                    monitor, wTask.ProductID, wTask.ProductNo, wTask.LineID, wTask.LineName, wTask.CustomerID,
                    APSConstans.GetCRMCustomer(wTask.CustomerID).CustomerName,
                    APSConstans.GetCRMCustomer(wTask.CustomerID).CustomerCode, wTask.OrderID, wTask.PartNo,
                    wTask.PartID, APSConstans.GetFPCPartName(wTask.PartID), APSConstans.GetFPCPart(wTask.PartID).Code,
                    "", "", wBaseTime, "", "", wBaseTime, 1, wLoginUser.ID, wLoginUser.Name, Calendar.getInstance(),
                    wOMSOrder.OrderNo, wBaseTime);
            wWMSPickDemand.SourceType = WMSPickDemandSourceType.ScrapApproval.getValue();
            wWMSPickDemand.SourceID = wItemList.get(0).NewSourceID;
            wWMSPickDemand.SourceCode = wItemList.get(0).NewSourceCode;
            int wDemandID = WMSPickDemandDAO.getInstance().Update(wLoginUser, wWMSPickDemand, wErrorCode);
            if (wDemandID <= 0) {
                return;
            }
            // ④创建领料需求单明细

            int wIndex = 1;
            for (APSBOMItem wAPSBOMItem : wItemList) {

                double wFQTY = wAPSBOMItem.Number;
                int wMaterialType = 0;
                if (wMaterialTypeMap.containsKey(wAPSBOMItem.MaterialID)) {
                    wMaterialType = wMaterialTypeMap.get(wAPSBOMItem.MaterialID);
                }
                // 根据最小包装计算需求
                if (wMaterialPackMap.containsKey(wAPSBOMItem.MaterialID)
                        && wMaterialType == MSSMaterialType.RecoilMaterial.getValue() && wIsSendRecoilMaterial) {
                    double wMinPack = wMaterialPackMap.get(wAPSBOMItem.MaterialID);
                    if (wMinPack > 0) {
                        int wAreaID = APSUtils.getInstance().GetAreaID(wAPSBOMItem.PartID);
                        wFQTY = WMSServiceImpl.getInstance().WMS_GetRealLLNumber(wLoginUser, wMinPack,
                                wAPSBOMItem.MaterialID, wAPSBOMItem.Number, wAreaID, wErrorCode).Result;
                    }
                }

                WMSPickDemandItem wWMSPickDemandItem = new WMSPickDemandItem(0, wDemandID, wAPSBOMItem.MaterialID,
                        wAPSBOMItem.MaterialNo, wAPSBOMItem.MaterialName, wAPSBOMItem.Number, wOMSOrder.OrderNo,
                        wTask.PartPointID, APSConstans.GetFPCPartPoint(wTask.PartPointID).Code.replace("PS-", ""),
                        APSConstans.GetFPCPartPointName(wTask.PartPointID), String.valueOf(wIndex), "",
                        wAPSBOMItem.ReplaceType, SFCReplaceType.getEnumType(wAPSBOMItem.ReplaceType).getLable(),
                        wAPSBOMItem.OutsourceType, SFCOutSourceType.getEnumType(wAPSBOMItem.OutsourceType).getLable(),
                        wAPSBOMItem.AssessmentType, "", wBaseTime, wWMSPickDemand.PartID, 1, wAPSBOMItem.Number,
                        wAPSBOMItem.OrderNum);
                wWMSPickDemandItem.FQTY = wFQTY;
                wWMSPickDemandItem.IsOriDis = wAPSBOMItem.OriginalType == 1 ? "是" : "否";

                int wItemID = WMSPickDemandItemDAO.getInstance().Update(wLoginUser, wWMSPickDemandItem, wErrorCode);
                if (wItemID > 0 && wWMSPickDemandItem.FQTY == 0) {
                    WMSServiceImpl.getInstance().WMS_RecoilMaterialUse(wLoginUser, wItemID);
                }
                wIndex++;
            }

            // ①手动推送
            String autoSendWMS = Configuration.readConfigString("autoSendWMS", "config/config");
            if (autoSendWMS.equals("1")) {
                WMSServiceImpl.getInstance().WMS_ManualPush(wLoginUser, wDemandID);
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    /**
     * 创建配送单
     */
    private void SendToWMSByQualityLoss(BMSEmployee wLoginUser, SFCQualityLossBPM wTask, List<APSBOMItem> wItemList) {
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            boolean wOutsourcingPlan = Configuration.readConfigString("OutsourcingPlan", "config/config").equals(
                    "1");
            boolean wIsSendRecoilMaterial = Configuration.readConfigString("IsSendRecoilMaterial", "config/config")
                    .equals(
                            "1");
            Map<Integer, Integer> wMaterialTypeMap = MRPMaterialPlanDAO.getInstance().GetMaterialTypeMap(wLoginUser,
                    wItemList.stream().map(p -> p.MaterialID).distinct().collect(Collectors.toList()), wErrorCode);
            if (!wOutsourcingPlan) {
                // 委外偶修、委外必须不推送
                wItemList.removeIf(p -> p.ReplaceType == 0 && p.OutsourceType == 2);
                if (wItemList.size() <= 0) {
                    return;
                }
            }

            if (!wIsSendRecoilMaterial) {
                // 反冲不推送
                List<Integer> wFCList = new ArrayList<>();
                for (int wMaterialID : wMaterialTypeMap.keySet()) {
                    int wType = wMaterialTypeMap.get(wMaterialID);
                    if (wType == MSSMaterialType.RecoilMaterial.getValue()) {
                        wFCList.add(wMaterialID);
                    }
                }
                wItemList.removeIf(p -> wFCList.stream().anyMatch(q -> q == p.MaterialID));
                if (wItemList.size() <= 0) {
                    return;
                }
            }

            Calendar wBaseTime = Calendar.getInstance();
            wBaseTime.set(2000, 0, 1, 0, 0, 0);

            String wCode = WMSPickDemandDAO.getInstance().GetNewCode(wLoginUser, wErrorCode);
            Calendar wTime = Calendar.getInstance();

            Calendar expectTime1 = Calendar.getInstance();
            expectTime1.set(wTime.get(Calendar.YEAR), wTime.get(Calendar.MONTH), wTime.get(Calendar.DATE), 0, 0, 0);

            Calendar expectTime2 = Calendar.getInstance();
            expectTime2.set(wTime.get(Calendar.YEAR), wTime.get(Calendar.MONTH), wTime.get(Calendar.DATE), 12, 0, 0);

            String monitorNo = "";
            String monitor = "";
            BMSEmployee wUser = WMSPickDemandDAO.getInstance().GetMonitorByPart(wLoginUser, wTask.PartID, wErrorCode);
            if (StringUtils.isNotEmpty(wUser.LoginID)) {
                monitorNo = wUser.LoginID;
                monitor = wUser.Name;
            }

            OMSOrder wOMSOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wTask.OrderID, wErrorCode);

            // 获取物料最小包装字典
            List<Integer> wMaterialIDList = wItemList.stream().map(p -> p.MaterialID).distinct()
                    .collect(Collectors.toList());
            Map<Integer, Double> wMaterialPackMap = MRPMaterialPlanDAO.getInstance().GetMaterialPackMap(wLoginUser,
                    wMaterialIDList, wErrorCode);

            WMSPickDemand wWMSPickDemand = new WMSPickDemand(0, "1900",
                    String.valueOf(WMSOrderType.LineOrder.getValue()), wCode, expectTime1, expectTime2, monitorNo,
                    monitor, wTask.ProductID, wTask.ProductNo, wTask.LineID, wTask.LineName, wTask.CustomerID,
                    APSConstans.GetCRMCustomer(wTask.CustomerID).CustomerName,
                    APSConstans.GetCRMCustomer(wTask.CustomerID).CustomerCode, wTask.OrderID, wTask.PartNo,
                    wTask.PartID, APSConstans.GetFPCPartName(wTask.PartID), APSConstans.GetFPCPart(wTask.PartID).Code,
                    "", "", wBaseTime, "", "", wBaseTime, 1, wLoginUser.ID, wLoginUser.Name, Calendar.getInstance(),
                    wOMSOrder.OrderNo, wBaseTime);
            wWMSPickDemand.SourceType = WMSPickDemandSourceType.QualityLoss.getValue();
            wWMSPickDemand.SourceID = wItemList.get(0).NewSourceID;
            wWMSPickDemand.SourceCode = wItemList.get(0).NewSourceCode;
            int wDemandID = WMSPickDemandDAO.getInstance().Update(wLoginUser, wWMSPickDemand, wErrorCode);
            if (wDemandID <= 0) {
                return;
            }
            // ④创建领料需求单明细

            int wIndex = 1;
            for (APSBOMItem wAPSBOMItem : wItemList) {

                double wFQTY = wAPSBOMItem.Number;
                int wMaterialType = 0;
                if (wMaterialTypeMap.containsKey(wAPSBOMItem.MaterialID)) {
                    wMaterialType = wMaterialTypeMap.get(wAPSBOMItem.MaterialID);
                }
                // 根据最小包装计算需求
                if (wMaterialPackMap.containsKey(wAPSBOMItem.MaterialID)
                        && wMaterialType == MSSMaterialType.RecoilMaterial.getValue() && wIsSendRecoilMaterial) {
                    double wMinPack = wMaterialPackMap.get(wAPSBOMItem.MaterialID);
                    if (wMinPack > 0) {
                        int wAreaID = APSUtils.getInstance().GetAreaID(wAPSBOMItem.PartID);
                        wFQTY = WMSServiceImpl.getInstance().WMS_GetRealLLNumber(wLoginUser, wMinPack,
                                wAPSBOMItem.MaterialID, wAPSBOMItem.Number, wAreaID, wErrorCode).Result;
                    }
                }

                WMSPickDemandItem wWMSPickDemandItem = new WMSPickDemandItem(0, wDemandID, wAPSBOMItem.MaterialID,
                        wAPSBOMItem.MaterialNo, wAPSBOMItem.MaterialName, wAPSBOMItem.Number, wOMSOrder.OrderNo,
                        wTask.PartPointID, APSConstans.GetFPCPartPoint(wTask.PartPointID).Code.replace("PS-", ""),
                        APSConstans.GetFPCPartPointName(wTask.PartPointID), String.valueOf(wIndex), "",
                        wAPSBOMItem.ReplaceType, SFCReplaceType.getEnumType(wAPSBOMItem.ReplaceType).getLable(),
                        wAPSBOMItem.OutsourceType, SFCOutSourceType.getEnumType(wAPSBOMItem.OutsourceType).getLable(),
                        wAPSBOMItem.AssessmentType, "", wBaseTime, wWMSPickDemand.PartID, 1, wAPSBOMItem.Number,
                        wAPSBOMItem.OrderNum);
                wWMSPickDemandItem.FQTY = wFQTY;
                wWMSPickDemandItem.IsOriDis = wAPSBOMItem.OriginalType == 1 ? "是" : "否";

                int wItemID = WMSPickDemandItemDAO.getInstance().Update(wLoginUser, wWMSPickDemandItem, wErrorCode);
                if (wItemID > 0 && wWMSPickDemandItem.FQTY == 0) {
                    WMSServiceImpl.getInstance().WMS_RecoilMaterialUse(wLoginUser, wItemID);
                }
                wIndex++;
            }

            // ①手动推送
            String autoSendWMS = Configuration.readConfigString("autoSendWMS", "config/config");
            if (autoSendWMS.equals("1")) {
                WMSServiceImpl.getInstance().WMS_ManualPush(wLoginUser, wDemandID);
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    /**
     * 维护偶换件的推送SAP状态
     */
    private void UpdateSFCBOMTaskSAPStatus(BMSEmployee wLoginUser, String wMsg, int wSFCBOMTaskID) {
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            SFCBOMTask wTask = (SFCBOMTask) SFCBOMTaskDAO.getInstance().BPM_GetTaskInfo(wLoginUser,
                    wSFCBOMTaskID, "",
                    wErrorCode);
            if (!StringUtils.isEmpty(wMsg)) {
                if (wMsg.contains("失败") || wMsg.contains("E")) {
                    wTask.SAPStatus = 2;
                    wTask.SAPStatusText = wMsg;
                    SFCBOMTaskDAO.getInstance().Update(wLoginUser, wTask, wErrorCode);

                    // ①发送通知消息给黄刚，通知他创建工序。
                    APSBOMUtils.getInstance().SendMessageToTechToCreateStep(wLoginUser, wTask.PartNo, wMsg, wTask.ID);
                } else if (wMsg.contains("S")) {
                    wTask.SAPStatus = 1;
                    wTask.SAPStatusText = "推送成功";
                    SFCBOMTaskDAO.getInstance().Update(wLoginUser, wTask, wErrorCode);
                }
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    /**
     * 维护偶换件的推送SAP状态
     */
    private void UpdateSFCScrapApprovalBPMSAPStatus(BMSEmployee wLoginUser, String wMsg, int wSFCScrapApprovalBPM) {
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            SFCScrapApprovalBPM wTask = (SFCScrapApprovalBPM) SFCScrapApprovalBPMDAO.getInstance().BPM_GetTaskInfo(
                    wLoginUser,
                    wSFCScrapApprovalBPM, "",
                    wErrorCode);
            if (!StringUtils.isEmpty(wMsg)) {
                if (wMsg.contains("失败") || wMsg.contains("E")) {
                    wTask.SAPStatus = 2;
                    wTask.SAPStatusText = wMsg;
                    SFCScrapApprovalBPMDAO.getInstance().Update(wLoginUser, wTask, wErrorCode);

                    // ①发送通知消息给黄刚，通知他创建工序。
                    APSBOMUtils.getInstance().SendMessageToTechToCreateStep(wLoginUser, wTask.PartNo, wMsg, wTask.ID);
                } else if (wMsg.contains("S")) {
                    wTask.SAPStatus = 1;
                    wTask.SAPStatusText = "推送成功";
                    SFCScrapApprovalBPMDAO.getInstance().Update(wLoginUser, wTask, wErrorCode);
                }
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }


    @Override
    public ServiceResult<List<APSTaskPart>> APS_QueryMonthPlanByMonth(BMSEmployee wLoginUser, int wYear, int wMonth) {
        ServiceResult<List<APSTaskPart>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            // ①开始时间
            Calendar wStartTime = Calendar.getInstance();
            wStartTime.set(wYear, wMonth - 1, 1, 0, 0, 0);
            // ②结束时间
            Calendar wEndTime = Calendar.getInstance();
            wEndTime.set(wYear, wMonth, 1, 0, 0, 0);

            wResult.Result = APSTaskPartDAO.getInstance().APS_QueryMonthPlanByMonth(wLoginUser, wStartTime, wEndTime,
                    wErrorCode);

            List<OMSOrder> wOMSOrderList = new ArrayList<>();
            if (wResult.Result.size() > 0) {
                List<Integer> wOrderIDList = wResult.Result.stream().map(p -> p.OrderID).distinct()
                        .collect(Collectors.toList());
                wOMSOrderList = OMSOrderDAO.getInstance().SelectListByIDList(wLoginUser, wOrderIDList, wErrorCode);
            }
            wResult.CustomResult.put("OMSOrderList", wOMSOrderList);

            // 多条件去重
            wResult.Result = wResult.Result.stream()
                    .collect(Collectors.collectingAndThen(Collectors.toCollection(
                                    () -> new TreeSet<>(Comparator.comparing(o -> o.getOrderID() + ";" + o.getPartID()))),
                            ArrayList::new));

            // 工位排序
            OrderPart(wResult.Result);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    /**
     * 工位排序
     */
    private void OrderPart(List<APSTaskPart> wList) {
        try {
            List<LFSWorkAreaStation> wWSList = new ArrayList<>(APSConstans.GetLFSWorkAreaStationList().values());
            for (APSTaskPart wAPSTaskPart : wList) {
                if (wWSList.stream().anyMatch(p -> p.StationID == wAPSTaskPart.PartID)) {
                    wAPSTaskPart.PartOrder = wWSList.stream().filter(p -> p.StationID == wAPSTaskPart.PartID)
                            .findFirst().get().OrderNum;
                } else {
                    wAPSTaskPart.PartOrder = 0;
                }
            }
            // 排序
            wList.sort(Comparator.comparing(APSTaskPart::getPartOrder));
        } catch (Exception e) {
            logger.error(e.toString());
        }
    }

    @Override
    public ServiceResult<List<APSTaskPart>> APS_QueryWeekPlanByWeek(BMSEmployee wLoginUser, Calendar wStartTime,
                                                                    Calendar wEndTime) {
        ServiceResult<List<APSTaskPart>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            wResult.Result = APSTaskPartDAO.getInstance().APS_QueryWeekPlanByWeek(wLoginUser, wStartTime, wEndTime,
                    wErrorCode);

            List<OMSOrder> wOMSOrderList = new ArrayList<>();
            if (wResult.Result.size() > 0) {
                List<Integer> wOrderIDList = wResult.Result.stream().map(p -> p.OrderID).distinct()
                        .collect(Collectors.toList());
                wOMSOrderList = OMSOrderDAO.getInstance().SelectListByIDList(wLoginUser, wOrderIDList, wErrorCode);
            }
            wResult.CustomResult.put("OMSOrderList", wOMSOrderList);

            // 多条件去重
            wResult.Result = wResult.Result.stream()
                    .collect(Collectors.collectingAndThen(Collectors.toCollection(
                                    () -> new TreeSet<>(Comparator.comparing(o -> o.getOrderID() + ";" + o.getPartID()))),
                            ArrayList::new));

            // 工位排序
            OrderPart(wResult.Result);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> APS_SendToSAPPro(BMSEmployee wLoginUser, int wOrderID, int wSFCBOMTaskID) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            OMSOrder wOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wOrderID, wErrorCode);

            int wBOMID = APSBOMItemDAO.getInstance().GetCurrentStandardBOMID(wLoginUser, wOrder.ProductID,
                    wOrder.LineID, wOrder.CustomerID, wOrder.RouteID, wErrorCode);

            if (wOrder.RouteID <= 0) {
                wBOMID = 0;
            }

            List<MSSBOMItem> wMSSBOMItemList = null;
            if (wBOMID > 0) {
                wMSSBOMItemList = WMSServiceImpl.getInstance()
                        .MSS_QueryBOMItemAll(wLoginUser, wBOMID, -1, -1, -1, -1, -1, -1, -1, -1).List(MSSBOMItem.class);
            }

            if (wMSSBOMItemList == null || wMSSBOMItemList.size() <= 0) {

                // 返回提示信息
                wResult.FaultCode = StringUtils.Format("提示：【{0}】该车辆无当前标准BOM，创建台车BOM失败!", wOrder.PartNo);

                // 此处推送消息，告知为何创建台车bom失败
                List<BFCMessage> wBFCMessageList = new ArrayList<>();
                BFCMessage wMessage = null;
                int wShiftID = MESServer.MES_QueryShiftID(wLoginUser.CompanyID, Calendar.getInstance(),
                        APSShiftPeriod.Day, FMCShiftLevel.Day, 0);
                // 发送任务消息到人员
                wMessage = new BFCMessage();
                wMessage.Active = 0;
                wMessage.CompanyID = 0;
                wMessage.CreateTime = Calendar.getInstance();
                wMessage.EditTime = Calendar.getInstance();
                wMessage.ID = 0;
                wMessage.MessageID = 0;
                wMessage.Title = StringUtils.Format("【台车BOM】提示", BPMEventModule.StationTip.getLable());
                wMessage.MessageText = wResult.FaultCode;
                wMessage.ModuleID = BPMEventModule.StationTip.getValue();
                wMessage.ResponsorID = StringUtils.parseInt(Configuration.readConfigString("bomUser", "config/config"));
                wMessage.ShiftID = wShiftID;
                wMessage.StationID = 0;
                wMessage.Type = BFCMessageType.Notify.getValue();
                wBFCMessageList.add(wMessage);

                CoreServiceImpl.getInstance().BFC_UpdateMessageList(wLoginUser, wBFCMessageList);

                return wResult;
            }

            List<APSBOMItem> wResultList = new ArrayList<>();

            APSBOMItem wBOMItem = null;

            for (MSSBOMItem wMSSBOMItem : wMSSBOMItemList) {

                if (wMSSBOMItem.Active != 1)
                    continue;

                if (wMSSBOMItem.ReplaceType == 2 && wMSSBOMItem.OutsourceType == 1) {

                    wBOMItem = new APSBOMItem(wMSSBOMItem, wOrder.LineID, wOrder.ProductID, wOrder.CustomerID,
                            wOrder.ID, wOrder.OrderNo, wOrder.PartNo);

                    wBOMItem.SourceType = APSBOMSourceType.StandardBOM.getValue();
                    wBOMItem.SourceID = wMSSBOMItem.ID;
                    wBOMItem.AuditorID = wLoginUser.ID;
                    wBOMItem.EditorID = wLoginUser.ID;
                    wBOMItem.AuditTime = Calendar.getInstance();
                    wBOMItem.EditTime = Calendar.getInstance();

                    wResultList.add(wBOMItem);
                }
            }

            // 评估类型赋值
            wResultList.forEach(p -> {
                if (p.OutsourceType == 1) {
                    p.AssessmentType = "修复旧件";
                }
            });

            APSServiceImpl.getInstance().APS_UpdateBOMItemList(wLoginUser, wResultList, wSFCBOMTaskID, 0, null);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> APS_ChangeLogAddToSAP(BMSEmployee wLoginUser, int wLogID) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            TCMMaterialChangeLog wLog = TCMMaterialChangeLogDAO.getInstance().SelectByID(wLoginUser, wLogID,
                    wErrorCode);
            List<TCMMaterialChangeItems> wList = wLog.ItemList.stream()
                    .filter(p -> p.ChangeType == TCMChangeType.MaterialInsert.getValue()
                            && (p.ReplaceType == 1 || p.OutsourceType == 1))
                    .collect(Collectors.toList());
            if (wList.size() > 0) {
                List<MSSBOMItem> wBOMItemList = CloneTool.CloneArray(wList, MSSBOMItem.class);

                String[] wStrs = wLog.OrderIDList.split(",");
                for (String wOrderStr : wStrs) {
                    int wOrderID = StringUtils.parseInt(wOrderStr);
                    if (wOrderID <= 0) {
                        continue;
                    }

                    OMSOrder wOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wOrderID, wErrorCode);

                    List<APSBOMItem> wResultList = new ArrayList<>();

                    APSBOMItem wBOMItem = null;

                    for (MSSBOMItem wMSSBOMItem : wBOMItemList) {

                        if (wMSSBOMItem.Active != 1)
                            continue;

                        if (wMSSBOMItem.ReplaceType == 1 || wMSSBOMItem.OutsourceType == 1) {

                            wBOMItem = new APSBOMItem(wMSSBOMItem, wOrder.LineID, wOrder.ProductID, wOrder.CustomerID,
                                    wOrder.ID, wOrder.OrderNo, wOrder.PartNo);

                            wBOMItem.SourceType = APSBOMSourceType.StandardBOM.getValue();
                            wBOMItem.SourceID = wMSSBOMItem.ID;
                            wBOMItem.AuditorID = wLoginUser.ID;
                            wBOMItem.EditorID = wLoginUser.ID;
                            wBOMItem.AuditTime = Calendar.getInstance();
                            wBOMItem.EditTime = Calendar.getInstance();

                            wResultList.add(wBOMItem);
                        }
                    }

                    // 评估类型赋值
                    wResultList.forEach(p -> {
                        if (p.OutsourceType == 1) {
                            p.AssessmentType = "修复旧件";
                        }
                    });

                    APSServiceImpl.getInstance().APS_UpdateBOMItemList(wLoginUser, wResultList, 0, 0, null);
                }
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<MCSLogInfo>> MCS_QueryLogList(BMSEmployee wLoginUser, String wProductNo,
                                                            String wLineName, String wCustomerName, String wPartNo,
                                                            String wFileType, String wVersionNo, Calendar wStartTime,
                                                            Calendar wEndTime, Pagination wPagination) {
        ServiceResult<List<MCSLogInfo>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            wResult.Result = MCSLogInfoDAO.getInstance().SelectListPro(wLoginUser, -1, wCustomerName, wLineName,
                    wProductNo, wPartNo, "", wFileType, wVersionNo, wStartTime,
                    wEndTime, wPagination, wErrorCode);

            // 处理返回的文件路径数据
            for (MCSLogInfo wMCSLogInfo : wResult.Result) {
                wMCSLogInfo.FilePath = wMCSLogInfo.FilePath.replace(
                        "/data/apache-tomcat-8.5.47/webapps/MESLOCOAPS/WEB-INF/classes/static/datasource",
                        "/data/meslogs/datasource_aps");
                wMCSLogInfo.FilePath = wMCSLogInfo.FilePath.replace(
                        "/data/apache-tomcat-8.5.47/webapps/MESWSDL/WEB-INF/classes/static/datasource",
                        "/data/meslogs/datasource_wsdl");
                wMCSLogInfo.FilePath = wMCSLogInfo.FilePath.replace(
                        "/data/apache-tomcat-8.5.47/webapps/MESQMS/WEB-INF/classes/static/datasource",
                        "/data/meslogs/datasource_qms");
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<APSSchedulingVersionBPM>> APS_QuerySchedulingVersionBPMEmployeeAllWeb(
            BMSEmployee wLoginUser, int wAPSShiftPeriod, int wStatus, int wOrderID, Calendar wStartTime,
            Calendar wEndTime) {
        ServiceResult<List<APSSchedulingVersionBPM>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            List<Integer> wIDList = new ArrayList<>();
            if (wOrderID > 0) {
                // 根据订单查询审批记录ID集合
                wIDList = APSSchedulingVersionBPMDAO.getInstance().SelectIDListByOrder(wLoginUser, wOrderID,
                        wErrorCode);
                if (wIDList.size() <= 0) {
                    return wResult;
                }
            }

            switch (wStatus) {
                case 1:
                    wResult.Result.addAll(APSSchedulingVersionBPMDAO.getInstance().SelectList(wLoginUser, -1, "", -1,
                            -1,
                            "", "", wAPSShiftPeriod, -1, new ArrayList<>(Collections.singletonList(20)), wIDList,
                            wStartTime,
                            wEndTime,
                            wErrorCode));
                    break;
                case 0:
                    wResult.Result.addAll(APSSchedulingVersionBPMDAO.getInstance().SelectList(wLoginUser, -1, "", -1,
                            -1,
                            "", "", wAPSShiftPeriod, -1, new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5)), wIDList, null,
                            null,
                            wErrorCode));
                    break;
                default:
                    wResult.Result.addAll(APSSchedulingVersionBPMDAO.getInstance().SelectList(wLoginUser, -1, "", -1,
                            -1,
                            "", "", wAPSShiftPeriod, -1, null, wIDList, wStartTime, wEndTime, wErrorCode));
                    break;
            }
            wResult.Result.sort((o1, o2) -> o2.SubmitTime.compareTo(o1.SubmitTime));

            if (wResult.Result.size() <= 0 || wStatus == 1) {
                return wResult;
            }
            List<BPMTaskBase> wBaseList = APSSchedulingVersionBPMDAO.getInstance().BPM_GetUndoTaskList(wLoginUser,
                    wLoginUser.ID, wErrorCode);

            if (wBaseList == null || wBaseList.size() <= 0) {
                return wResult;
            }
            for (BPMTaskBase wTaskBase : wBaseList) {
                if (!(wTaskBase instanceof APSSchedulingVersionBPM))
                    continue;
                APSSchedulingVersionBPM wAPSSchedulingVersionBPM = (APSSchedulingVersionBPM) wTaskBase;
                wAPSSchedulingVersionBPM.TagTypes = TaskQueryType.ToHandle.getValue();
                for (int i = 0; i < wResult.Result.size(); i++) {
                    if (wResult.Result.get(i).ID == wAPSSchedulingVersionBPM.ID)
                        wResult.Result.set(i, wAPSSchedulingVersionBPM);
                }
            }

        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<String> APS_CheckSchedulingVersionBPM(BMSEmployee wLoginUser, APSSchedulingVersionBPM wTask) {
        ServiceResult<String> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            // 提交
            if (wTask.Status == 2) {
                List<APSTaskPart> wList = APSTaskPartDAO.getInstance().SelectListByIDList(wLoginUser,
                        wTask.TaskPartIDList, wErrorCode);
                if (wList.stream().anyMatch(p -> p.Status != 1)) {
                    wResult.Result += "提示：请提交未排的数据!";
                    return wResult;
                }
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<APSBOMLog>> APS_QueryBOMLogList(BMSEmployee wLoginUser, int wOrderID, int wLineID,
                                                              int wProductID, int wCustomerID, int wStatus,
                                                              Calendar wStartTime, Calendar wEndTime) {
        ServiceResult<List<APSBOMLog>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            wResult.Result = APSBOMLogDAO.getInstance().SelectList(wLoginUser, -1, wProductID, wLineID, wCustomerID,
                    wOrderID, wStatus, wStartTime, wEndTime, wErrorCode);

            // 时间降序排序
            wResult.Result.sort(Comparator.comparing(APSBOMLog::getCreateTime, Comparator.reverseOrder()));

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<APSBOMLog> APS_QueryBOMLogByID(BMSEmployee wLoginUser, int wID) {
        ServiceResult<APSBOMLog> wResult = new ServiceResult<>();
        wResult.Result = new APSBOMLog();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wResult.Result = APSBOMLogDAO.getInstance().SelectByID(wLoginUser, wID, wErrorCode);

            if ((wResult.Result.Status == 2 || wResult.Result.Status == 3)
                    && wResult.Result.Msg.contains("请用事务码ZPM1011配置标准工序")) {
                SAPResult wSAPResult = JSON.parseObject(wResult.Result.Msg, SAPResult.class);
                String[] wStrs = wSAPResult.msg.split("\\|");
                for (String wStr : wStrs) {
                    if (wResult.Result.ErrorList.stream().anyMatch(p -> p.equals(wStr))) {
                        continue;
                    }
                    wResult.Result.ErrorList.add(wStr);
                }

                // 如果错误列表有值，转换赋值
                if (wResult.Result.ErrorList.size() > 0) {
                    wResult.Result.Msg = StringUtils.Join("\r\n", wResult.Result.ErrorList);
                }
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<APSManuCapacityStep> APS_QueryManuCapacityStep(BMSEmployee wLoginUser, int wID) {
        ServiceResult<APSManuCapacityStep> wResult = new ServiceResult<>();
        wResult.Result = new APSManuCapacityStep();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wResult.Result = APSManuCapacityStepDAO.getInstance().SelectByID(wLoginUser, wID, wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<APSManuCapacityStep>> APS_QueryManuCapacityStepList(BMSEmployee wLoginUser, int wLineID,
                                                                                  int wPartID, int wStatus,
                                                                                  int wActive) {
        ServiceResult<List<APSManuCapacityStep>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            List<APSManuCapacityStep> wList = APSManuCapacityStepDAO.getInstance().SelectList(wLoginUser, -1, wLineID,
                    wPartID, -1, wStatus, wActive, wErrorCode);

            // ①根据工位、修程获取产线单元明细，工序列表
            List<Integer> wStepList = APSManuCapacityStepDAO.getInstance().SelectLineUnitStepList(wLoginUser, wLineID,
                    wPartID, wErrorCode);
            // ②遍历赋值
            APSManuCapacityStep wAPSManuCapacityStep;
            for (Integer wStepID : wStepList) {
                if (wList.stream().anyMatch(p -> p.StepID == wStepID)) {
                    wAPSManuCapacityStep = wList.stream().filter(p -> p.StepID == wStepID).findFirst().get();
                } else {
                    wAPSManuCapacityStep = new APSManuCapacityStep();
                    wAPSManuCapacityStep.ID = 0;
                    wAPSManuCapacityStep.LineID = wLineID;
                    wAPSManuCapacityStep.LineName = APSConstans.GetFMCLineName(wLineID);
                    wAPSManuCapacityStep.PartID = wPartID;
                    wAPSManuCapacityStep.PartName = APSConstans.GetFPCPartName(wPartID);
                    wAPSManuCapacityStep.StepID = wStepID;
                    wAPSManuCapacityStep.StepName = APSConstans.GetFPCPartPointName(wStepID);
                }
                wResult.Result.add(wAPSManuCapacityStep);
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> APS_UpdateManuCapacityStep(BMSEmployee wLoginUser, APSManuCapacityStep wCapacity) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wResult.Result = APSManuCapacityStepDAO.getInstance().Update(wLoginUser, wCapacity, wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public void APS_ActiveManuCapacityStepList(BMSEmployee wLoginUser, List<Integer> wIDList, int wActive) {
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            APSManuCapacityStepDAO.getInstance().Active(wLoginUser, wIDList, wActive, wErrorCode);
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    public List<FPCPartTemp> mFPCPartListTemp = new ArrayList<>();

    @Override
    public ServiceResult<List<APSTaskPart>> APS_AutoSchedulingStep(BMSEmployee wLoginUser, int wOrderID,
                                                                   APSShiftPeriod wShiftPeriod, Calendar wStartTime,
                                                                   Calendar wEndTime, int wWorkDay, int wLimitMinutes,
                                                                   List<APSTaskPart> wMutualTaskList, int wPartID) {
        ServiceResult<List<APSTaskPart>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            OMSOrder wOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wOrderID, wErrorCode);
            // 1、获取排程参数
            // ①工位任务列表
            List<APSTaskPart> wOrderPartIssuedList = new ArrayList<>();
            // ②委外订单列表
            List<OMSOutsourceOrder> wOutsourceOrderList = new ArrayList<>();
            // ③工位工时列表
            List<APSManuCapacity> wManuCapacityList = getManuCapacityList(wLoginUser, wOrder, wPartID);
            // ④获取工艺路径
            Map<Integer, List<FPCRoutePart>> wRoutePartListMap = getRoutePartListMap(wLoginUser, wOrder, wPartID);
            // ⑤产线列表
            List<FMCLine> wLineList = new ArrayList<>(APSConstans.GetFMCLineList().values());
            wLineList.removeIf(p -> p.Active != 1);
            // ⑥获取安装明细列表
            List<APSInstallation> wAPSInstallationList = new ArrayList<>();
            // ⑦获取拆解明细列表
            List<APSDismantling> wAPSDismantlingList = new ArrayList<>();
            // ⑧冲突消息
            List<APSMessage> wMessageList = new ArrayList<>();
            // ⑨订单列表
            List<OMSOrder> wOrderList = new ArrayList<>(Collections.singletonList(wOrder));
            // 2、调用自动排程接口
            wResult = APSServiceImpl.getInstance().APS_AutoTaskPart(wLoginUser, wOrderList, wShiftPeriod,
                    wOrderPartIssuedList, wOutsourceOrderList, wStartTime, wEndTime, wRoutePartListMap,
                    wManuCapacityList, wAPSInstallationList, wAPSDismantlingList, wMessageList, wWorkDay, wLimitMinutes,
                    wMutualTaskList);
            // 3、返回数据处理
            // ①赋值WBS号
            if (wResult.Result.size() > 0) {
                wResult.Result.forEach(p -> {
                    if (StringUtils.isEmpty(p.PartNo)) {
                        p.PartNo = wOrderList.stream().filter(q -> q.ID == p.OrderID).findFirst().get().OrderNo;
                    }
                });
            }
            // ②赋值工艺路线
            if (wResult.Result != null && wResult.Result.size() > 0) {
                wResult.Result.forEach(
                        p -> {
                            p.RouteID = wOrderList.stream().filter(q -> q.ID == p.OrderID).findFirst().get().RouteID;
                            p.LineName = APSConstans.GetFMCLineName(p.LineID);
                            p.PartName = APSConstans.GetFPCPartPointName(p.PartID);
                        });
            }
            // ③甘特图Tip生成
            if (wResult.Result != null) {
                for (APSTaskPart wItem : wResult.Result) {
                    Optional<APSManuCapacity> wOption = wManuCapacityList.stream()
                            .filter(p -> p.LineID == wItem.LineID && p.PartID == wItem.PartID).findFirst();
                    if (wOption.isPresent()) {
                        APSManuCapacity wCapacity = wOption.get();
                        wItem.TaskText = StringUtils.Format("工位容量：{0}\n排程周期(天)：{1}", wCapacity.FQTY,
                                wCapacity.WorkHour);
                    }
                }
            }
            // ④处理月排程结尾堆积问题
            Calendar wMiddleTime = wEndTime;

            Calendar wLastTime = (Calendar) wEndTime.clone();
            wLastTime.add(Calendar.DATE, 1);

            if (wShiftPeriod == APSShiftPeriod.Month && wResult.Result != null && wResult.Result.size() > 0) {
                List<APSTaskPart> wTempList = wResult.Result.stream().filter(p -> p.StartTime.compareTo(wEndTime) > 0)
                        .collect(Collectors.toList());
                if (wTempList.size() > 0) {
                    APSTaskPart wMinItem = wTempList.stream().min(Comparator.comparing(APSTaskPart::getEndTime)).get();
                    wMiddleTime = wMinItem.EndTime;

                    wResult.Result.forEach(p -> {
                        if (p.StartTime.compareTo(wEndTime) > 0) {
                            double wHour = CalIntervalHour(wEndTime, p.StartTime);
                            p.StartTime = wEndTime;
                            p.EndTime.add(Calendar.HOUR_OF_DAY, (int) wHour * -1);
                        }
                    });
                }
            }
            // 4、其他返回参数构造
            // ①StartTime
            wResult.CustomResult.put("StartTime", wStartTime);
            // ②MiddleTime
            wResult.CustomResult.put("MiddleTime", wMiddleTime);
            // ③RouteList
            List<FPCRoute> wRouteList = new ArrayList<>();
            wResult.CustomResult.put("RouteList", wRouteList);
            // ④Msg
            // 产线列表
            if (wLineList.size() <= 0)
                return wResult;
            // 工位列表
            List<FPCPart> wPartList = null;
            // if (mFPCPartListTemp.stream().anyMatch(p -> p.RouteID == wOrder.RouteID &&
            // p.PartID == wPartID)) {
            // wPartList = mFPCPartListTemp.stream().filter(p -> p.RouteID == wOrder.RouteID
            // && p.PartID == wPartID)
            // .findFirst().get().List;
            // } else {
            List<FPCPart> wPList = APSTaskPartDAO.getInstance().SelectStepPart(wLoginUser, wOrderID, wPartID,
                    wErrorCode);

            FPCPartTemp wTemp = new FPCPartTemp();
            wTemp.RouteID = wOrder.RouteID;
            wTemp.PartID = wPartID;
            wTemp.List = wPList;
            mFPCPartListTemp.add(wTemp);

            wPartList = wPList;
            // }

            // list排序
            for (APSTaskPart wAPSTaskPart : wResult.Result) {
                if (wPartList.stream().noneMatch(p -> p.ID == wAPSTaskPart.PartID)) {
                    continue;
                }

                wAPSTaskPart.TaskLineID = wPartList.stream().filter(p -> p.ID == wAPSTaskPart.PartID).findFirst()
                        .get().FactoryID;
            }
            // 排序
            wResult.Result.sort(Comparator.comparing(APSTaskPart::getTaskLineID));

            if (wPartList == null || wPartList.size() <= 0)
                return wResult;

            int wFlag = 1;
            int wOrderFlag = 1;
            List<APSTaskPart> wTreeList = new ArrayList<>();
            List<LFSWorkAreaStation> wWorkAreaStationList = getLFSWorkAreaStationList(wPartList);
            if (wWorkAreaStationList.size() <= 0) {
                return wResult;
            }

            for (LFSWorkAreaStation wItem : wWorkAreaStationList) {
                // 工位
                APSTaskPart wAPSTaskPart = new APSTaskPart();
                wAPSTaskPart.PartID = wItem.StationID;
                wAPSTaskPart.PartOrder = wOrderFlag++;
                Optional<FPCPart> wOption = wPartList.stream().filter(p -> p.ID == wItem.StationID).findFirst();
                wOption.ifPresent(fpcPart -> wAPSTaskPart.PartName = fpcPart.Name);
                wAPSTaskPart.UniqueID = wFlag++;
                wTreeList.add(wAPSTaskPart);

                for (FMCLine wLine : wLineList) {
                    // 产线
                    APSTaskPart wLinePart = new APSTaskPart();
                    wLinePart.UniqueID = wFlag++;
                    wLinePart.LineID = wLine.ID;
                    wLinePart.LineName = wLine.Name;
                    wAPSTaskPart.TaskPartList.add(wLinePart);

                    // 工位任务
                    wLinePart.TaskPartList = wResult.Result.stream()
                            .filter(p -> p.PartID == wItem.StationID && p.LineID == wLine.ID)
                            .collect(Collectors.toList());
                    if (wLinePart.TaskPartList.size() > 0) {
                        for (APSTaskPart wItemPart : wLinePart.TaskPartList) {
                            wItemPart.UniqueID = wFlag++;
                            wItemPart.PartOrder = wAPSTaskPart.PartOrder;

                            // 为冲突消息设置唯一标识
                            if (wMessageList.size() <= 0)
                                continue;
                            Optional<APSMessage> wMessageOption = wMessageList.stream()
                                    .filter(p -> p.LineID == wItemPart.LineID && p.PartID == wItemPart.PartID
                                            && p.OrderID == wItemPart.OrderID)
                                    .findFirst();
                            if (wMessageOption.isPresent()) {
                                APSMessage wMessage = wMessageOption.get();
                                wMessage.UniqueID = wItemPart.UniqueID;
                                wItemPart.APSMessage = wMessage.MessageText;
                            }
                        }
                    } else {
                        wLinePart.TaskPartList = new ArrayList<>();
                        wLinePart.TaskPartList.add(new APSTaskPart());
                    }
                }
            }
            wResult.CustomResult.put("Msg", wMessageList);
            // ⑤TreeList
            wResult.CustomResult.put("TreeList", wTreeList);
            // ⑥TableInfoList
            List<Map<String, Object>> wTableMap = new ArrayList<>();
            Map<String, Object> wHeadMap = new HashMap<>();
            List<FPCPart> wStationList = new ArrayList<>();
            // 排序
            if (wWorkAreaStationList.size() > 0) {
                wWorkAreaStationList.sort(Comparator.comparing(LFSWorkAreaStation::getOrderNum));
            }
            for (LFSWorkAreaStation wItem : wWorkAreaStationList) {
                Optional<FPCPart> wOption = wPartList.stream().filter(p -> p.ID == wItem.StationID).findFirst();
                if (wOption.isPresent()) {
                    wHeadMap.put("Station_" + wItem.StationID, wOption.get().Name);
                    wStationList.add(wOption.get());
                }
            }
            wTableMap.add(wHeadMap);
            wTableMap.addAll(APSServiceImpl.getInstance().ChangeToTable(wOrderList, wResult.Result,
                    wWorkAreaStationList).Result);
            wResult.CustomResult.put("TableInfoList", wTableMap);
            // ⑦OrderColumn
            wResult.CustomResult.put("OrderColumn", wStationList);
            // ⑧MaxTime
            // 最大时间
            Calendar wMaxTime = wResult.Result.stream().max(Comparator.comparing(APSTaskPart::getEndTime))
                    .get().EndTime;
            wResult.CustomResult.put("MaxTime", wMaxTime);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    public List<FPCRoutePartTemp> mFPCRoutePartTempList = new ArrayList<>();

    /**
     * 获取工序工艺路径
     */
    private Map<Integer, List<FPCRoutePart>> getRoutePartListMap(BMSEmployee wLoginUser, OMSOrder wOrder, int wPartID) {
        Map<Integer, List<FPCRoutePart>> wResult = new HashMap<>();
        try {
            List<FPCRoutePartPoint> wList = null;
            if (mFPCRoutePartTempList != null && mFPCRoutePartTempList.stream()
                    .anyMatch(p -> p.RouteID == wOrder.RouteID && p.PartID == wPartID)) {
                wList = mFPCRoutePartTempList.stream().filter(p -> p.RouteID == wOrder.RouteID && p.PartID == wPartID)
                        .findFirst().get().List;
            } else {
                wList = FMCServiceImpl.getInstance()
                        .FPC_QueryRoutePartPointListByRouteID(wLoginUser, wOrder.RouteID, wPartID)
                        .List(FPCRoutePartPoint.class);
                FPCRoutePartTemp wTemp = new FPCRoutePartTemp();
                wTemp.RouteID = wOrder.RouteID;
                wTemp.PartID = wPartID;
                wTemp.List = wList;
                mFPCRoutePartTempList.add(wTemp);
            }

            List<FPCRoutePart> wRoutePartList = new ArrayList<>();
            for (FPCRoutePartPoint wFPCRoutePartPoint : wList) {
                FPCRoutePart wItem = CloneTool.Clone(wFPCRoutePartPoint, FPCRoutePart.class);
                wItem.PrevPartID = wFPCRoutePartPoint.PrevStepID;
                wItem.NextPartIDMap = wFPCRoutePartPoint.NextStepIDMap;
                wItem.PartID = wFPCRoutePartPoint.PartPointID;
                wRoutePartList.add(wItem);
            }
            wResult.put(wOrder.ID, wRoutePartList);
        } catch (Exception e) {
            logger.error(e.toString());
        }
        return wResult;
    }

    public List<FPCCapacityStepTemp> mFPCCapacityStepTempList = new ArrayList<>();

    /**
     * 获取工序工时
     */
    private List<APSManuCapacity> getManuCapacityList(BMSEmployee wLoginUser, OMSOrder wOrder, int wPartID) {
        List<APSManuCapacity> wResult = new ArrayList<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            List<APSManuCapacityStep> wList = null;

            if (mFPCCapacityStepTempList != null && mFPCCapacityStepTempList.stream()
                    .anyMatch(p -> p.RouteID == wOrder.RouteID && p.PartID == wPartID)) {
                wList = mFPCCapacityStepTempList.stream()
                        .filter(p -> p.RouteID == wOrder.RouteID && p.PartID == wPartID).findFirst().get().List;
            } else {
                wList = APSManuCapacityStepDAO.getInstance().SelectList(wLoginUser, -1, wOrder.LineID, wPartID, -1, -1,
                        1, wErrorCode);
                FPCCapacityStepTemp wTemp = new FPCCapacityStepTemp();
                wTemp.RouteID = wOrder.RouteID;
                wTemp.PartID = wPartID;
                wTemp.List = wList;
                mFPCCapacityStepTempList.add(wTemp);
            }

            for (APSManuCapacityStep wAPSManuCapacityStep : wList) {
                APSManuCapacity wItem = CloneTool.Clone(wAPSManuCapacityStep, APSManuCapacity.class);
                wItem.PartID = wAPSManuCapacityStep.StepID;
                wItem.PartName = wAPSManuCapacityStep.StepName;
                wResult.add(wItem);
            }
        } catch (Exception e) {
            logger.error(e.toString());
        }
        return wResult;
    }

    /**
     * 工位转化为工区工位
     */
    private List<LFSWorkAreaStation> getLFSWorkAreaStationList(List<FPCPart> wPartList) {
        List<LFSWorkAreaStation> wResult = new ArrayList<>();
        try {
            for (FPCPart wFPCPart : wPartList) {
                LFSWorkAreaStation wItem = new LFSWorkAreaStation();
                wItem.StationID = wFPCPart.ID;
                wItem.StationName = wFPCPart.Name;
                wResult.add(wItem);
            }
        } catch (Exception e) {
            logger.error(e.toString());
        }
        return wResult;
    }

    /**
     * 计算开始时间和结束时间之间的间隔小时
     *
     * @param wStartTime 开始时间
     * @param wEndTime   结束时间
     * @return 间隔小时
     */
    public double CalIntervalHour(Calendar wStartTime, Calendar wEndTime) {
        double wResult = 0.0;
        try {
            Calendar wBaseTime = Calendar.getInstance();
            wBaseTime.set(2000, 0, 1);
            if (wStartTime == null) {
                wStartTime = wBaseTime;
            }
            if (wEndTime == null) {
                wEndTime = wBaseTime;
            }
            if (wStartTime.compareTo(wEndTime) >= 0) {
                return wResult;
            }

            long wStart = wStartTime.getTime().getTime();
            long wEnd = wEndTime.getTime().getTime();
            long wMinutes = (wEnd - wStart) / (1000 * 60);
            double wHour = (double) wMinutes / 60;
            wResult = formatDouble(wHour);
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
        return wResult;
    }

    /**
     * 四舍五入保留两位小数
     */
    public double formatDouble(double wNumber) {
        double wResult = 0.0;
        try {
            // 如果不需要四舍五入，可以使用RoundingMode.DOWN
            BigDecimal wBG = new BigDecimal(wNumber).setScale(2, RoundingMode.UP);
            wResult = wBG.doubleValue();
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> APS_BomItemPropertyChange(BMSEmployee wLoginUser, int wID, String wDeleteID,
                                                            double wNumber) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            // ①根据ID查询台车bom
            APSBOMItem wBomItem = APSBOMItemDAO.getInstance().APS_QueryBOMItemByID(wLoginUser, wID, wErrorCode);
            if (wBomItem == null || wBomItem.ID <= 0) {
                wResult.FaultCode += "提示：此ID不存在!";
                return wResult;
            }

            if (StringUtils.isNotEmpty(wDeleteID)) {
                wBomItem.DeleteID = wDeleteID;
            }

            if (wNumber > 0) {
                wBomItem.Number = wNumber;
            }

            // ③更新MES台车Bom
            APSBOMItemDAO.getInstance().APS_UpdateBOMItem(wLoginUser, wBomItem, wErrorCode);

            // ③构造推送json
            String wJson = APSBOMUtils.getInstance().ChangeToJson(new ArrayList<>(Collections.singletonList(wBomItem)), "U");
            // ④推送数据
            if (StringUtils.isNotEmpty(wJson)) {
                OMSOrder wOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wBomItem.OrderID, wErrorCode);

                String wReturnMsg = SendToSAP(wLoginUser, wJson, wOrder.OrderNo, 0, wOrder, 0,
                        new ArrayList<>(Collections.singletonList(wID)), 2);
                if (wReturnMsg.contains("失败") || wReturnMsg.contains("E")) {
                    wResult.FaultCode += wReturnMsg;
                }
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> APS_BomItemPropertyChange(BMSEmployee wLoginUser, int wOrderID, List<Integer> wAPSBOMItemIDList, String wDeleteID, double wNumber) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            OMSOrder wOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wOrderID, wErrorCode);

            if (wErrorCode.Result != 0) {
                wResult.FaultCode += MESException.getEnumType(wErrorCode.Result).getLable();
                return wResult;
            }
            if (wOrder == null || wOrder.ID <= 0) {
                wResult.FaultCode += "提示：此订单不存在!";
                return wResult;
            }

            List<APSBOMItem> wAPSBOMItemList = APSBOMItemDAO.getInstance().SelectByIDList(wLoginUser, wAPSBOMItemIDList, wErrorCode);
            if (wErrorCode.Result != 0) {
                wResult.FaultCode += MESException.getEnumType(wErrorCode.Result).getLable();
                return wResult;
            }
            List<Integer> wIDList = new ArrayList<>();
            for (APSBOMItem wBomItem : wAPSBOMItemList) {

                if (wBomItem == null || wBomItem.ID <= 0) {
                    continue;
                }
                wIDList.add(wBomItem.ID);
                if (StringUtils.isNotEmpty(wDeleteID)) {
                    wBomItem.DeleteID = "X";
                }

                if (wNumber > 0) {
                    wBomItem.Number = wNumber;
                }
                // ③更新MES台车Bom
                APSBOMItemDAO.getInstance().APS_UpdateBOMItem(wLoginUser, wBomItem, wErrorCode);

                wBomItem.ErrorCode += MESException.getEnumType(wErrorCode.Result).getLable();
            }

            // ③构造推送json
            String wJson = APSBOMUtils.getInstance().ChangeToJson(wAPSBOMItemList, "U");
            // ④推送数据
            if (StringUtils.isNotEmpty(wJson)) {
                //OMSOrder wOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wBomItem.OrderID, wErrorCode);

                String wReturnMsg = SendToSAP(wLoginUser, wJson, wOrder.OrderNo, 0, wOrder, 0,
                        wIDList, 2);
                if (wReturnMsg.contains("失败") || wReturnMsg.contains("E")) {
                    wResult.FaultCode += wReturnMsg;
                }
            }

        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> APS_AssessTypeChange(BMSEmployee wLoginUser) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            // ①查询出偶换件委外必修件评估类型为常规新件的偶换件ID集合
            List<Integer> wIDList = APSBOMItemDAO.getInstance().SelectAssessErrorIDList(wLoginUser, wErrorCode);
            if (wIDList == null || wIDList.size() <= 0) {
                wResult.FaultCode += "提示：没有偶换件委外必须件评估类型为常规新件的台车bom";
                return wResult;
            }
            // ②根据偶换件ID集合获取偶换件集合
            List<APSBOMItem> wList = APSBOMItemDAO.getInstance().SelectByIDList(wLoginUser, wIDList, wErrorCode);
            if (wList == null || wList.size() <= 0) {
                wResult.FaultCode += "提示：没有偶换件委外必须件评估类型为常规新件的台车bom";
                return wResult;
            }
            // ③提取订单集合
            List<Integer> wOrderIDList = wList.stream().map(p -> p.OrderID).distinct().collect(Collectors.toList());
            // ④遍历订单，修改属性，并且推送台车bom到SAP
            for (Integer wOrderID : wOrderIDList) {
                List<APSBOMItem> wOrderBomList = wList.stream().filter(p -> p.OrderID == wOrderID)
                        .collect(Collectors.toList());

                for (APSBOMItem wAPSBOMItem : wOrderBomList) {
                    wAPSBOMItem.DeleteID = "X";
                    APSBOMItemDAO.getInstance().APS_UpdateBOMItem(wLoginUser, wAPSBOMItem, wErrorCode);
                }

                List<APSBOMItem> wDeleteList = CloneTool.CloneArray(wOrderBomList, APSBOMItem.class);

                wOrderBomList.forEach(p -> p.AssessmentType = "修复旧件");

                List<APSBOMItem> wInsertList = new ArrayList<>();
                for (APSBOMItem wAPSBOMItem : wOrderBomList) {
                    wAPSBOMItem.ID = 0;
                    wAPSBOMItem.DeleteID = "";
                    wAPSBOMItem.ID = APSBOMItemDAO.getInstance().APS_UpdateBOMItem(wLoginUser, wAPSBOMItem, wErrorCode);
                    wInsertList.add(wAPSBOMItem);
                }

                wDeleteList.addAll(wInsertList);

                // ③构造推送json
                String wJson = APSBOMUtils.getInstance().ChangeToJson(wDeleteList, "U");
                // ④推送数据
                if (StringUtils.isNotEmpty(wJson)) {
                    OMSOrder wOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wOrderID, wErrorCode);

                    String wReturnMsg = SendToSAP(wLoginUser, wJson, wOrder.OrderNo, 0, wOrder, 0, null, 2);
                    if (wReturnMsg.contains("失败") || wReturnMsg.contains("E")) {
                        wResult.FaultCode = wResult.FaultCode + wReturnMsg;
                    }
                }
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<APSTaskStepPlan>> APS_QueryStepPlanList(BMSEmployee wLoginUser, String wOrderIDs,
                                                                      String wPartIDs, int wAPSShfitPeriod) {
        ServiceResult<List<APSTaskStepPlan>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            String[] wOrders = wOrderIDs.split(",");

            wResult.Result = APSTaskStepPlanDAO.getInstance().SelectList(wLoginUser, wOrderIDs, wPartIDs,
                    wAPSShfitPeriod, wErrorCode);

            List<Integer> wOrderIDList = new ArrayList<>();
            String[] wStrs = wOrders;
            for (String wStr : wStrs) {
                int wID = StringUtils.parseInt(wStr);
                wOrderIDList.add(wID);
            }

            List<Integer> wPartIDList = new ArrayList<>();
            wStrs = wPartIDs.split(",");
            for (String wStr : wStrs) {
                int wID = StringUtils.parseInt(wStr);
                wPartIDList.add(wID);
            }

            List<StepPlanTableTemp> wTableInfoMap = new ArrayList<>();
            List<StepPlanTableTemp> wOrderColumnMap = new ArrayList<>();

            List<FPCPartPoint> wStepList = new ArrayList<>(APSConstans.GetFPCPartPointList().values());

            // 订单排序
            List<OMSOrder> wOList = OMSOrderDAO.getInstance().SelectListByIDList(wLoginUser, wOrderIDList, wErrorCode);
            wOList.sort(Comparator.comparing(OMSOrder::getERPID).thenComparing(OMSOrder::getRealReceiveDate));
            // 结果排序
            wResult.Result = OrderResult(wOList, wResult.Result);

            List<FPCPart> wPartOrderList = APSManuCapacityStepDAO.getInstance().SelectListByPartList(wLoginUser,
                    StringUtils.parseIntList(wPartIDs.split(",")), wErrorCode);

            for (int wOrderID : wOrderIDList) {
                for (int wPartID : wPartIDList) {
                    // TableInfo
                    StepPlanTableTemp wTableInfo = new StepPlanTableTemp();
                    wTableInfo.OrderID = wOrderID;
                    wTableInfo.PartID = wPartID;

                    List<Map<String, Object>> wTableMap = new ArrayList<>();
                    Map<String, Object> wHeadMap = new HashMap<>();
                    List<FPCPart> wStationList = new ArrayList<>();

                    List<LFSWorkAreaStation> wWorkAreaStationList = new ArrayList<>();

                    List<APSTaskStepPlan> wTempList = wResult.Result.stream()
                            .filter(p -> p.OrderID == wOrderID && p.PartID == wPartID).collect(Collectors.toList());

                    // 工序排序
                    OrderTempList(wTempList, wPartOrderList);

                    for (APSTaskStepPlan wItem : wTempList) {
                        FPCPart wPart = new FPCPart();
                        if (wStepList.stream().anyMatch(p -> p.ID == wItem.StepID)) {
                            FPCPartPoint wStep = wStepList.stream().filter(p -> p.ID == wItem.StepID).findFirst().get();
                            wPart.ID = wStep.ID;
                            wPart.Name = wStep.Name;
                            wPart.FactoryID = wItem.OrderNum;
                        }
                        wHeadMap.put("Station_" + wItem.StepID, wPart.Name);
                        wStationList.add(wPart);

                        LFSWorkAreaStation wLFSWorkAreaStation = new LFSWorkAreaStation();
                        wLFSWorkAreaStation.StationID = wPart.ID;
                        wLFSWorkAreaStation.StationName = wPart.Name;
                        wWorkAreaStationList.add(wLFSWorkAreaStation);
                    }

                    List<OMSOrder> wOrderList = OMSOrderDAO.getInstance().SelectListByIDList(wLoginUser,
                            new ArrayList<>(Collections.singletonList(wOrderID)), wErrorCode);

                    List<APSTaskPart> wTaskPartList = new ArrayList<>();
                    for (APSTaskStepPlan wAPSTaskStepPlan : wResult.Result) {
                        APSTaskPart wAPSTaskPart = new APSTaskPart();
                        wAPSTaskPart.OrderID = wAPSTaskStepPlan.OrderID;
                        wAPSTaskPart.PartID = wAPSTaskStepPlan.StepID;
                        wAPSTaskPart.StartTime = wAPSTaskStepPlan.StartTime;
                        wAPSTaskPart.EndTime = wAPSTaskStepPlan.EndTime;
                        wTaskPartList.add(wAPSTaskPart);
                    }

                    wTableMap.add(wHeadMap);
                    wTableMap.addAll(APSServiceImpl.getInstance().ChangeToTableByEndTime(wOrderList, wTaskPartList,
                            wWorkAreaStationList).Result);

                    List<FPCPart> wNRList = new ArrayList<>();
                    for (FPCPart wFPCPart : wStationList) {
                        if (wNRList.stream().noneMatch(p -> p.ID == wFPCPart.ID)) {
                            wNRList.add(wFPCPart);
                        }
                    }

                    wTableInfo.Data = wTableMap;
                    wTableInfoMap.add(wTableInfo);
                    // OrderColumn
                    StepPlanTableTemp wOrderColumn = new StepPlanTableTemp();
                    wOrderColumn.OrderID = wOrderID;
                    wOrderColumn.PartID = wPartID;
                    wOrderColumn.Data = wNRList;
                    wOrderColumnMap.add(wOrderColumn);
                }
            }

            // 表格数据返回
            wResult.CustomResult.put("TableInfoList", wTableInfoMap);
            wResult.CustomResult.put("OrderColumn", wOrderColumnMap);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    /**
     * 工序排序
     */
    private void OrderTempList(List<APSTaskStepPlan> wTempList, List<FPCPart> wPartOrderList) {
        try {
            if (wTempList == null || wTempList.size() <= 0) {
                return;
            }
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            // 查询是否设置了手动排序，若设置了，修改FactoryID
            List<FPCPart> wOList = wPartOrderList.stream().filter(p -> p.QTPartID == wTempList.get(0).PartID)
                    .collect(Collectors.toList());

            if (wOList.stream().anyMatch(p -> p.FactoryID > 0)) {
                for (APSTaskStepPlan wAPSTaskStepPlan : wTempList) {
                    if (wOList.stream().noneMatch(p -> p.ID == wAPSTaskStepPlan.StepID)) {
                        continue;
                    }
                    wAPSTaskStepPlan.OrderNum = wOList.stream().filter(p -> p.ID == wAPSTaskStepPlan.StepID).findFirst()
                            .get().FactoryID;
                }
            }
            // 排序
            wTempList.sort(Comparator.comparing(APSTaskStepPlan::getOrderNum));
        } catch (Exception e) {
            logger.error(e.toString());
        }
    }

    @Override
    public ServiceResult<Integer> APS_AddAPSBOMToSAP(BMSEmployee wLoginUser, int wBOMID, int wOrderID) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            // ①查询新版标准BOM子项集合
            List<MSSBOMItem> wMSSBOMItemList = null;
            if (wBOMID > 0) {
                wMSSBOMItemList = WMSServiceImpl.getInstance()
                        .MSS_QueryBOMItemAll(wLoginUser, wBOMID, -1, -1, -1, -1, -1, -1, -1, -1).List(MSSBOMItem.class);
            }
            if (wMSSBOMItemList == null || wMSSBOMItemList.size() <= 0) {
                wResult.FaultCode += "提示：查询标准BOM失败";
                return wResult;
            }
            // ②筛选出必换件、必修件
            wMSSBOMItemList = wMSSBOMItemList.stream().filter(p -> p.ReplaceType == 1 || p.OutsourceType == 1)
                    .collect(Collectors.toList());
            // ③遍历查询订单是否存在，若不存在，加入待推送集合
            List<MSSBOMItem> wToSendList = new ArrayList<>();
            for (MSSBOMItem wMSSBOMItem : wMSSBOMItemList) {
                boolean wCheckResult = APSBOMItemDAO.getInstance().IsExist(wLoginUser, wOrderID, wMSSBOMItem.PlaceID,
                        wMSSBOMItem.PartPointID, wMSSBOMItem.MaterialID, wMSSBOMItem.ReplaceType,
                        wMSSBOMItem.OutsourceType, wErrorCode);
                if (!wCheckResult) {
                    wToSendList.add(wMSSBOMItem);
                }
            }
            // ④推送给SAP
            OMSOrder wOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wOrderID, wErrorCode);

            List<APSBOMItem> wResultList = new ArrayList<>();

            APSBOMItem wBOMItem = null;

            for (MSSBOMItem wMSSBOMItem : wToSendList) {

                wBOMItem = new APSBOMItem(wMSSBOMItem, wOrder.LineID, wOrder.ProductID, wOrder.CustomerID, wOrder.ID,
                        wOrder.OrderNo, wOrder.PartNo);

                wBOMItem.SourceType = APSBOMSourceType.StandardBOM.getValue();
                wBOMItem.SourceID = wMSSBOMItem.ID;
                wBOMItem.AuditorID = wLoginUser.ID;
                wBOMItem.EditorID = wLoginUser.ID;
                wBOMItem.AuditTime = Calendar.getInstance();
                wBOMItem.EditTime = Calendar.getInstance();

                wResultList.add(wBOMItem);
            }

            // 验证台车BOM
            String wMsg = APSBOMUtils.getInstance().CheckAPSBOM(wResultList, wOrder);
            if (StringUtils.isNotEmpty(wMsg)) {

                // 发送创建台车bom的消息
                APSBOMUtils.getInstance().SendAPSBOMMessage(wLoginUser, wMsg, wOrder);

                // 返回提示信息
                wResult.FaultCode = wMsg;
                return wResult;
            }

            // 评估类型赋值
            wResultList.forEach(p -> {
                if (p.OutsourceType == 1) {
                    p.AssessmentType = "修复旧件";
                }
            });

            for (APSBOMItem wItem : wResultList) {
                wItem.ID = APSBOMItemDAO.getInstance().APS_UpdateBOMItem(wLoginUser, wItem, wErrorCode);
                wItem.ProductNo = wOrder.ProductNo;
                wItem.LineName = wOrder.LineName;
                wItem.CustomerCode = APSConstans.GetCRMCustomer(wItem.CustomerID).CustomerCode;
                wItem.PartPointName = APSConstans.GetFPCPartPointName(wItem.PartPointID);
            }

            String wSendSAP = Configuration.readConfigString("isSendSAP", "config/config");

            if (wSendSAP.equals("1")) {
                // ①推送台车BOM给SAP
                String wJson = APSBOMUtils.getInstance().ChangeToJson(wResultList, "U");
                if (StringUtils.isNotEmpty(wJson)) {
                    String wResultMsg = SendToSAP(wLoginUser, wJson, wOrder.OrderNo, 0, wOrder, 0,
                            wResultList.stream().map(p -> p.ID).collect(Collectors.toList()), 2);
                    if (wResultMsg.contains("变更成功")) {
                        // 创建必换件的配送单，分工位创建
                        CreatePickDemandOrderByPart(wLoginUser, wResultList, wErrorCode);
                    }
                }
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    /**
     * 创建必换件的配送单，分工位创建
     */
    private void CreatePickDemandOrderByPart(BMSEmployee wLoginUser, List<APSBOMItem> wResultList,
                                             OutResult<Integer> wErrorCode) {
        try {
            boolean wOutsourcingPlan = Configuration.readConfigString("OutsourcingPlan", "config/config").equals(
                    "1");
            boolean wIsSendRecoilMaterial = Configuration.readConfigString("IsSendRecoilMaterial", "config/config")
                    .equals(
                            "1");
            if (!wOutsourcingPlan) {
                wResultList.removeIf(p -> p.OutsourceType == 1);
            }
            // 反冲料是否移除，判断
            List<Integer> wFCList = new ArrayList<>();
            if (!wIsSendRecoilMaterial) {
                List<Integer> wMaterialIDList = wResultList.stream().map(p -> p.MaterialID).distinct()
                        .collect(Collectors.toList());
                Map<Integer, Integer> wMaterialTypeMap = MRPMaterialPlanDAO.getInstance().GetMaterialTypeMap(wLoginUser,
                        wMaterialIDList, wErrorCode);

                for (int wMaterialID : wMaterialTypeMap.keySet()) {
                    int wType = wMaterialTypeMap.get(wMaterialID);
                    if (wType == MSSMaterialType.RecoilMaterial.getValue()) {
                        wFCList.add(wMaterialID);
                    }
                }
                wResultList.removeIf(p -> wFCList.stream().anyMatch(q -> q == p.MaterialID));
            }

            if (wResultList.size() <= 0) {
                return;
            }

            OMSOrder wOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wResultList.get(0).OrderID, wErrorCode);

            // 提取工位列表
            List<Integer> wPartIDList = wResultList.stream().map(p -> p.PartID).distinct().collect(Collectors.toList());
            for (int wPartID : wPartIDList) {
                List<APSBOMItem> wItemList = wResultList.stream().filter(p -> p.PartID == wPartID)
                        .collect(Collectors.toList());

                // 创建配送单，并推送给wms
                // ③创建领料需求单
                Calendar wBaseTime = Calendar.getInstance();
                wBaseTime.set(2000, 0, 1, 0, 0, 0);

                String wCode = WMSPickDemandDAO.getInstance().GetNewCode(wLoginUser, wErrorCode);
                Calendar wTime = Calendar.getInstance();

                Calendar expectTime1 = Calendar.getInstance();
                expectTime1.set(wTime.get(Calendar.YEAR), wTime.get(Calendar.MONTH), wTime.get(Calendar.DATE), 0, 0, 0);

                Calendar expectTime2 = Calendar.getInstance();
                expectTime2.set(wTime.get(Calendar.YEAR), wTime.get(Calendar.MONTH), wTime.get(Calendar.DATE), 12, 0,
                        0);

                String monitorNo = "";
                String monitor = "";
                BMSEmployee wUser = WMSPickDemandDAO.getInstance().GetMonitorByPart(wLoginUser, wPartID,
                        wErrorCode);
                if (StringUtils.isNotEmpty(wUser.LoginID)) {
                    monitorNo = wUser.LoginID;
                    monitor = wUser.Name;
                }

                WMSPickDemand wWMSPickDemand = new WMSPickDemand(0, "1900",
                        String.valueOf(WMSOrderType.LineOrder.getValue()), wCode, expectTime1, expectTime2, monitorNo,
                        monitor, wItemList.get(0).ProductID, APSConstans.GetFPCProductNo(wItemList.get(0).ProductID),
                        wItemList.get(0).LineID, APSConstans.GetFMCLineName(wItemList.get(0).LineID),
                        wItemList.get(0).CustomerID,
                        APSConstans.GetCRMCustomer(wItemList.get(0).CustomerID).CustomerName,
                        APSConstans.GetCRMCustomer(wItemList.get(0).CustomerID).CustomerCode, wItemList.get(0).OrderID,
                        wItemList.get(0).PartNo, wItemList.get(0).PartID,
                        APSConstans.GetFPCPartName(wItemList.get(0).PartID),
                        APSConstans.GetFPCPart(wItemList.get(0).PartID).Code, "", "", wBaseTime, "", "", wBaseTime, 1,
                        wLoginUser.ID, wLoginUser.Name, Calendar.getInstance(), wItemList.get(0).WBSNo, wBaseTime);
                wWMSPickDemand.SourceType = WMSPickDemandSourceType.Plan.getValue();
                int wDemandID = WMSPickDemandDAO.getInstance().Update(wLoginUser, wWMSPickDemand, wErrorCode);
                if (wDemandID <= 0) {
                    return;
                }
                // ④创建领料需求单明细
                int wIndex = 1;

                // 获取物料最小包装字典
                Map<Integer, Double> wMaterialPackMap = MRPMaterialPlanDAO.getInstance().GetMaterialPackMap(wLoginUser,
                        wFCList, wErrorCode);

                for (APSBOMItem wMRPMaterialPlan : wItemList) {
                    double wFQTY = wMRPMaterialPlan.Number;
                    // 根据最小包装计算需求
                    if (wMaterialPackMap.containsKey(wMRPMaterialPlan.MaterialID)) {
                        double wMinPack = wMaterialPackMap.get(wMRPMaterialPlan.MaterialID);
                        if (wMinPack > 0) {
                            int wAreaID = APSUtils.getInstance().GetAreaID(wMRPMaterialPlan.PartID);
                            wFQTY = WMSServiceImpl.getInstance().WMS_GetRealLLNumber(wLoginUser, wMinPack,
                                    wMRPMaterialPlan.MaterialID, wMRPMaterialPlan.Number, wAreaID, wErrorCode).Result;
                        }
                    }

                    // 获取配套属性
                    String wGroup = "";
                    int wMaterialType = 0;
                    if (wMaterialPackMap.containsKey(wMRPMaterialPlan.MaterialID))
                        wMaterialType = MSSMaterialType.RecoilMaterial.getValue();
                    else
                        wMaterialType = MSSMaterialType.MainMaterial.getValue();

                    WMSPickDemandItem wWMSPickDemandItem = new WMSPickDemandItem(0, wDemandID,
                            wMRPMaterialPlan.MaterialID, wMRPMaterialPlan.MaterialNo, wMRPMaterialPlan.MaterialName,
                            wFQTY, wOrder.OrderNo, wMRPMaterialPlan.PartPointID,
                            APSConstans.GetFPCPartPoint(wMRPMaterialPlan.PartPointID).Code.replace("PS-", ""),
                            APSConstans.GetFPCPartPointName(wMRPMaterialPlan.PartPointID), String.valueOf(wIndex),
                            wGroup,
                            wMRPMaterialPlan.ReplaceType,
                            SFCReplaceType.getEnumType(wMRPMaterialPlan.ReplaceType).getLable(),
                            wMRPMaterialPlan.OutsourceType,
                            SFCOutSourceType.getEnumType(wMRPMaterialPlan.OutsourceType).getLable(),
                            wMRPMaterialPlan.AssessmentType, "", wBaseTime, wWMSPickDemand.PartID,
                            wMaterialType, wMRPMaterialPlan.Number, wMRPMaterialPlan.OrderNum);
                    int wItemID = WMSPickDemandItemDAO.getInstance().Update(wLoginUser, wWMSPickDemandItem, wErrorCode);
                    wWMSPickDemandItem.IsOriDis = wMRPMaterialPlan.OriginalType == 1 ? "是" : "否";

                    if (wItemID > 0 && wWMSPickDemandItem.FQTY == 0) {
                        WMSServiceImpl.getInstance().WMS_RecoilMaterialUse(wLoginUser, wItemID);
                    }
                    wIndex++;
                }
            }

        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    @Override
    public ServiceResult<Integer> APS_SaveStepPlan(BMSEmployee wLoginUser, List<APSTaskPart> wStepPlanList) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            if (wStepPlanList == null || wStepPlanList.size() <= 0) {
                return wResult;
            }

            List<Integer> wOrderIDList = wStepPlanList.stream().map(p -> p.OrderID).distinct()
                    .collect(Collectors.toList());
            List<Integer> wPartIDList = wStepPlanList.stream().map(p -> p.RealPartID).distinct()
                    .collect(Collectors.toList());

            for (int wOrderID : wOrderIDList) {
                OMSOrder wOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wOrderID, wErrorCode);

                for (int wPartID : wPartIDList) {

                    List<APSTaskPart> wToSaveList = wStepPlanList.stream()
                            .filter(p -> p.OrderID == wOrderID && p.RealPartID == wPartID).collect(Collectors.toList());
                    if (wToSaveList.size() <= 0) {
                        continue;
                    }

                    // ①转换为工序计划结构
                    /*
                     * 遍历保存工序计划
                     */
                    SimpleDateFormat wSDF = new SimpleDateFormat("yyyyMMdd");
                    int wShiftID = Integer.parseInt(wSDF.format(Calendar.getInstance().getTime()));
                    List<APSTaskStepPlan> wList = new ArrayList<>();
                    for (APSTaskPart wAPSTaskPart : wToSaveList) {
                        APSTaskStepPlan wPlan = new APSTaskStepPlan(0, wAPSTaskPart.OrderID, wOrder.PartNo, 0,
                                wOrder.LineID, wPartID, wAPSTaskPart.PartID, Calendar.getInstance(),
                                Calendar.getInstance(), wShiftID, wAPSTaskPart.StartTime, wAPSTaskPart.EndTime, 1, 1,
                                "", wOrder.ProductNo, "", "", "", wLoginUser.ID, "", wAPSTaskPart.TaskText, "");
                        wList.add(wPlan);
                    }
                    List<Integer> wStepIDList = wToSaveList.stream().map(p -> p.PartID).distinct()
                            .collect(Collectors.toList());
                    // ②查询存在的工序计划
                    List<APSTaskStepPlan> wEList = APSTaskStepPlanDAO.getInstance().SelectList(wLoginUser, wOrder.ID,
                            wPartID, wStepIDList, wStepPlanList.get(0).ShiftPeriod, wErrorCode);
                    // ③删除存在的工序计划
                    if (wEList.size() > 0) {
                        APSTaskStepPlanDAO.getInstance().DeleteList(wLoginUser, wEList, wErrorCode);
                    }
                    // ④遍历保存工序计划
                    for (APSTaskStepPlan wAPSTaskStepPlan : wList) {
                        wAPSTaskStepPlan.APSShiftPeriod = wStepPlanList.get(0).ShiftPeriod;
                        APSTaskStepPlanDAO.getInstance().Update(wLoginUser, wAPSTaskStepPlan, wErrorCode);
                    }
                }
            }

            // 同步部件工序对应工位的计划时间；解决时间不同步的问题
            ExecutorService wES = Executors.newFixedThreadPool(1);
            wES.submit(() -> APSTaskPartDAO.getInstance().SynchronizePlanTime(wLoginUser, wOrderIDList, wPartIDList,
                    wStepPlanList,
                    wErrorCode));
            wES.shutdown();

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<FPCRoute>> ASP_QueryRouteList(BMSEmployee wLoginUser, List<Integer> wRouteIDList,
                                                            int wPartID) {
        ServiceResult<List<FPCRoute>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            if (wRouteIDList == null || wRouteIDList.size() <= 0) {
                return wResult;
            }

            for (Integer wRouteID : wRouteIDList) {
                FPCRoute wRoute = FMCServiceImpl.getInstance().FPC_QueryRouteByID(wLoginUser, wRouteID)
                        .Info(FPCRoute.class);

                List<FPCRoutePartPoint> wList = FMCServiceImpl.getInstance()
                        .FPC_QueryRoutePartPointListByRouteID(wLoginUser, wRouteID, wPartID)
                        .List(FPCRoutePartPoint.class);

                List<FPCRoutePart> wRoutePartList = new ArrayList<>();
                for (FPCRoutePartPoint wFPCRoutePartPoint : wList) {
                    FPCRoutePart wFPCRoutePart = new FPCRoutePart();

                    wFPCRoutePart.ID = wFPCRoutePartPoint.ID;
                    wFPCRoutePart.RouteID = wFPCRoutePartPoint.RouteID;
                    wFPCRoutePart.PartID = wFPCRoutePartPoint.PartPointID;
                    wFPCRoutePart.PrevPartID = wFPCRoutePartPoint.PrevStepID;
                    wFPCRoutePart.NextPartIDMap = wFPCRoutePartPoint.NextStepIDMap;

                    wRoutePartList.add(wFPCRoutePart);
                }

                wRoute.PartList = wRoutePartList;

                wResult.Result.add(wRoute);
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public void APS_CancelDeleteX(BMSEmployee wLoginUser, int wBOMItemID) {
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            List<APSBOMItem> wList = APSBOMItemDAO.getInstance().SelectByIDList(wLoginUser,
                    new ArrayList<>(Collections.singletonList(wBOMItemID)), wErrorCode);

            for (APSBOMItem wAPSBOMItem : wList) {
                wAPSBOMItem.DeleteID = "";
                wAPSBOMItem.EditTime = Calendar.getInstance();

                APSBOMItemDAO.getInstance().APS_UpdateBOMItem(wLoginUser, wAPSBOMItem, wErrorCode);
            }

            OMSOrder wOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wList.get(0).OrderID, wErrorCode);

            String wJson = APSBOMUtils.getInstance().ChangeToJson(wList, "U");
            if (StringUtils.isNotEmpty(wJson)) {
                SendToSAP(wLoginUser, wJson, wOrder.OrderNo, 0, wOrder, 0, null, 2);
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    @Override
    public void SendSingleMaterial(BMSEmployee wLoginUser, int wBOMID, List<Integer> wBOMItemIDList,
                                   List<Integer> wOrderIDList) {
        try {
            List<MSSBOMItem> wMSSBOMItemList = null;
            if (wBOMID > 0) {
                wMSSBOMItemList = WMSServiceImpl.getInstance()
                        .MSS_QueryBOMItemAll(wLoginUser, wBOMID, -1, -1, -1, -1, -1, -1, -1, -1).List(MSSBOMItem.class);
                wMSSBOMItemList = wMSSBOMItemList.stream().filter(p -> wBOMItemIDList.stream().anyMatch(q -> q == p.ID))
                        .collect(Collectors.toList());
            }

            if (wMSSBOMItemList == null || wMSSBOMItemList.size() <= 0) {
                return;
            }

            OutResult<Integer> wErrorCode = new OutResult<>(0);

            for (int wOrderID : wOrderIDList) {
                OMSOrder wOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wOrderID, wErrorCode);

                List<APSBOMItem> wResultList = new ArrayList<>();

                APSBOMItem wBOMItem = null;

                for (MSSBOMItem wMSSBOMItem : wMSSBOMItemList) {

                    if (wMSSBOMItem.ReplaceType == 1 || wMSSBOMItem.OutsourceType == 1) {

                        wBOMItem = new APSBOMItem(wMSSBOMItem, wOrder.LineID, wOrder.ProductID, wOrder.CustomerID,
                                wOrder.ID, wOrder.OrderNo, wOrder.PartNo);

                        wBOMItem.SourceType = APSBOMSourceType.StandardBOM.getValue();
                        wBOMItem.SourceID = wMSSBOMItem.ID;
                        wBOMItem.AuditorID = wLoginUser.ID;
                        wBOMItem.EditorID = wLoginUser.ID;
                        wBOMItem.AuditTime = Calendar.getInstance();
                        wBOMItem.EditTime = Calendar.getInstance();

                        wResultList.add(wBOMItem);
                    }
                }

                // 评估类型赋值
                wResultList.forEach(p -> {
                    if (p.OutsourceType == 1) {
                        p.AssessmentType = "修复旧件";
                    }
                    if (p.ReplaceType == 1 && p.OutsourceType == 1) {
                        p.AssessmentType = "常规新件";
                    }
                });

                APSServiceImpl.getInstance().APS_UpdateBOMItemList(wLoginUser, wResultList, 0, 0, null);
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    @Override
    public ServiceResult<String> APS_DeleteListByImport(BMSEmployee wLoginUser, ExcelData result, int wOrderID) {
        ServiceResult<String> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            // ①解析出ID集合
            List<Integer> wIDList = new ArrayList<>();

            ExcelSheetData wSheet = result.sheetData.get(0);

            int wIndex = 0;
            for (ExcelLineData wExcelLineData : wSheet.lineData) {
                if (wIndex == 0) {
                    wIndex++;
                    continue;
                }
                wIDList.add(StringUtils.parseInt(wExcelLineData.colData.get(0).replace(".0", "")));
            }
            // ②添加删除标记
            List<APSBOMItem> wList = APSBOMItemDAO.getInstance().SelectByIDList(wLoginUser, wIDList, wErrorCode);
            for (APSBOMItem apsbomItem : wList) {
                apsbomItem.DeleteID = "X";
                APSBOMItemDAO.getInstance().APS_UpdateBOMItem(wLoginUser, apsbomItem, wErrorCode);
            }

            APSServiceImpl.getInstance().APS_UpdateBOMItemList(wLoginUser, wList, 0, 0, null);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public void APS_ChangeNumber(BMSEmployee wLoginUser, int wOrderID, int wAPSBOMID) {
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            List<Integer> wIDList = new ArrayList<>(Collections.singletonList(wAPSBOMID));
            List<APSBOMItem> wList = APSBOMItemDAO.getInstance().SelectByIDList(wLoginUser, wIDList, wErrorCode);

            for (APSBOMItem apsbomItem : wList) {
                apsbomItem.Number = 2.0;
                APSBOMItemDAO.getInstance().APS_UpdateBOMItem(wLoginUser, apsbomItem, wErrorCode);
            }

            APSServiceImpl.getInstance().APS_UpdateBOMItemList(wLoginUser, wList, 0, 0, null);
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    @Override
    public ServiceResult<List<APSTaskPart>> APS_StepPlanMore(BMSEmployee wLoginUser, List<APSStepPlanParam> wList) {
        ServiceResult<List<APSTaskPart>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            mFPCCapacityStepTempList = new ArrayList<>();
            mFPCRoutePartTempList = new ArrayList<>();
            mFPCPartListTemp = new ArrayList<>();

            List<StepPlanTableTemp> wTableInfoMap = new ArrayList<>();
            List<StepPlanTableTemp> wOrderColumnMap = new ArrayList<>();
            for (APSStepPlanParam wAPSStepPlanParam : wList) {
                ServiceResult<List<APSTaskPart>> wRst = APSServiceImpl.getInstance().APS_AutoSchedulingStep(wLoginUser,
                        wAPSStepPlanParam.OrderID, APSShiftPeriod.getEnumType(wAPSStepPlanParam.APSShiftPeriod),
                        wAPSStepPlanParam.StartTime, wAPSStepPlanParam.EndTime, wAPSStepPlanParam.WorkDay,
                        wAPSStepPlanParam.LimitMinutes, wAPSStepPlanParam.MutualTaskList, wAPSStepPlanParam.PartID);
                wRst.Result.forEach(p -> p.RealPartID = wAPSStepPlanParam.PartID);

                Object wTableInfoList = wRst.CustomResult.get("TableInfoList");
                Object wOrderColumn = wRst.CustomResult.get("OrderColumn");

                StepPlanTableTemp wTableInfoTemp = new StepPlanTableTemp();
                wTableInfoTemp.OrderID = wAPSStepPlanParam.OrderID;
                wTableInfoTemp.PartID = wAPSStepPlanParam.PartID;
                wTableInfoTemp.Data = wTableInfoList;
                wTableInfoMap.add(wTableInfoTemp);

                StepPlanTableTemp wOrderColumnTemp = new StepPlanTableTemp();
                wOrderColumnTemp.OrderID = wAPSStepPlanParam.OrderID;
                wOrderColumnTemp.PartID = wAPSStepPlanParam.PartID;
                wOrderColumnTemp.Data = wOrderColumn;
                wOrderColumnMap.add(wOrderColumnTemp);

                wResult.Result.addAll(wRst.Result);
            }

            String wOrderIDs = StringUtils.Join(",", wList.stream().map(p -> p.OrderID).collect(Collectors.toList()));
            String wPartIDs = StringUtils.Join(",", wList.stream().map(p -> p.PartID).collect(Collectors.toList()));

            List<FPCRoutePartPoint> wRouteList = FPCRouteDAO.getInstance().SelectRoutePartPointList(wLoginUser,
                    wOrderIDs, wPartIDs, wErrorCode);

            wResult.CustomResult.put("TableInfoListMap", wTableInfoMap);
            wResult.CustomResult.put("OrderColumnMap", wOrderColumnMap);
            wResult.CustomResult.put("RouteList", wRouteList);

            mFPCCapacityStepTempList.clear();
            mFPCRoutePartTempList.clear();
            mFPCPartListTemp.clear();

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> APS_QueryBOMID(BMSEmployee wLoginUser, int wSourceID, int wType,
                                                 String wCustomerCode) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            if (wType == APSBOMSourceType.StandardBOM.getValue()) {
                MSSBOM wBOM = SFCBOMTaskDAO.getInstance().APS_QueryBOMID(wLoginUser, wSourceID, wErrorCode);
                wResult.CustomResult.put("RouteID", wBOM.RouteID);
                wResult.CustomResult.put("BomID", wBOM.ID);
                wResult.CustomResult.put("BomName", wBOM.BOMName);
            } else if (wType == APSBOMSourceType.BOMChange.getValue()) {
                TCMMaterialChangeItems wItems = SFCBOMTaskDAO.getInstance().TCM_QueryChangeItems(wLoginUser, wSourceID,
                        wErrorCode);
                if (StringUtils.isNotEmpty(wItems.BOMNo2)) {
                    String[] wStrs = wItems.BOMNo2.split(",");
                    for (String wStr : wStrs) {
                        if (!wStr.contains(wCustomerCode)) {
                            continue;
                        }

                        MSSBOM wBOM = SFCBOMTaskDAO.getInstance().MSS_QueryIDByNo(wLoginUser, wStr, wErrorCode);
                        wResult.CustomResult.put("RouteID", wBOM.RouteID);
                        wResult.CustomResult.put("BomID", wBOM.ID);
                        wResult.CustomResult.put("BomName", wBOM.BOMName);
                    }
                } else {
                    wResult.CustomResult.put("RouteID", 0);
                    wResult.CustomResult.put("BomID", 0);
                    wResult.CustomResult.put("BomName", "");
                }
            } else if (wType == APSBOMSourceType.SFCBOMTask.getValue()) {
                int wSFCBOMTaskID = SFCBOMTaskItemDAO.getInstance().SelectByID(wLoginUser, wSourceID,
                        wErrorCode).SFCBOMTaskID;
                wResult.CustomResult.put("RouteID", 0);
                wResult.CustomResult.put("BomID", wSFCBOMTaskID);
                wResult.CustomResult.put("BomName", "");
            } else {
                wResult.CustomResult.put("RouteID", 0);
                wResult.CustomResult.put("BomID", 0);
                wResult.CustomResult.put("BomName", "");
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    /**
     * 自动计算部件计划
     */
    private ServiceResult<List<APSTaskStepPlan>> AutoCalcComponentPlan(BMSEmployee wLoginUser, String wOrderIDs,
                                                                       String wPartIDs, int wAPSShiftPeriod) {
        ServiceResult<List<APSTaskStepPlan>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            List<OMSOrder> wTotalOrderList = OMSOrderDAO.getInstance().SelectListByIDList(wLoginUser,
                    StringUtils.parseIntList(wOrderIDs.split(",")), wErrorCode);
            wOrderIDs = StringUtils.Join(",", wTotalOrderList.stream().map(p -> p.ID).collect(Collectors.toList()));

            String[] wOrders = wOrderIDs.split(",");

            // 根据订单、工位查询实际的工序计划
            List<APSTaskStep> wRealTaskStepList = APSTaskStepDAO.getInstance().SelectList(wLoginUser, wOrderIDs,
                    wPartIDs, wErrorCode);

            wResult.Result = APSTaskStepPlanDAO.getInstance().SelectList(wLoginUser, wOrderIDs, wPartIDs,
                    wAPSShiftPeriod, wErrorCode);

            // 查询周计划
            List<APSTaskPart> wTaskPartList1 = APSTaskPartDAO.getInstance().SelectListByOrdersAndPartIDs(wLoginUser,
                    wOrderIDs, wPartIDs, wErrorCode);
            wResult.Result.removeIf(
                    p -> wTaskPartList1.stream().noneMatch(q -> q.OrderID == p.OrderID && p.PartID == q.PartID));

            // 赋值真实的时间
            List<FPCPart> wPartOrderList = APSManuCapacityStepDAO.getInstance().SelectListByPartList(wLoginUser,
                    StringUtils.parseIntList(wPartIDs.split(",")), wErrorCode);

            Calendar wBaseTime = Calendar.getInstance();
            wBaseTime.set(2000, 0, 1, 0, 0, 0);
            for (APSTaskStepPlan wAPSTaskStepPlan : wResult.Result) {
                if (wRealTaskStepList.stream().anyMatch(p -> p.OrderID == wAPSTaskStepPlan.OrderID
                        && p.PartID == wAPSTaskStepPlan.PartID && p.StepID == wAPSTaskStepPlan.StepID)) {
                    APSTaskStep wTaskStep = wRealTaskStepList
                            .stream().filter(p -> p.OrderID == wAPSTaskStepPlan.OrderID
                                    && p.PartID == wAPSTaskStepPlan.PartID && p.StepID == wAPSTaskStepPlan.StepID)
                            .findFirst().get();
                    wAPSTaskStepPlan.RealStartTime = wTaskStep.StartTime;
                    wAPSTaskStepPlan.RealEndTime = wTaskStep.EndTime;
                    wAPSTaskStepPlan.StartTime = wTaskStep.PlanStartTime;
                    wAPSTaskStepPlan.EndTime = wTaskStep.PlanEndTime;
                    wAPSTaskStepPlan.Status = wTaskStep.Status;
                } else {
                    wAPSTaskStepPlan.RealStartTime = wBaseTime;
                    wAPSTaskStepPlan.RealEndTime = wBaseTime;
                    wAPSTaskStepPlan.StartTime = wBaseTime;
                    wAPSTaskStepPlan.EndTime = wBaseTime;
                }
            }

            List<Integer> wOrderIDList = new ArrayList<>();
            String[] wStrs = wOrders;
            for (String wStr : wStrs) {
                int wID = StringUtils.parseInt(wStr);
                wOrderIDList.add(wID);
            }

            List<Integer> wPartIDList = new ArrayList<>();
            wStrs = wPartIDs.split(",");
            for (String wStr : wStrs) {
                int wID = StringUtils.parseInt(wStr);
                wPartIDList.add(wID);
            }

            List<StepPlanTableTemp> wTableInfoMap = new ArrayList<>();
            List<StepPlanTableTemp> wOrderColumnMap = new ArrayList<>();

            List<FPCPartPoint> wStepList = new ArrayList<>(APSConstans.GetFPCPartPointList().values());

            // 订单排序
            List<OMSOrder> wOList = OMSOrderDAO.getInstance().SelectListByIDList(wLoginUser, wOrderIDList, wErrorCode);
            wOList.sort(Comparator.comparing(OMSOrder::getERPID).thenComparing(OMSOrder::getRealReceiveDate));
            // 结果排序
            wResult.Result = OrderResult(wOList, wResult.Result);

            // 查询工序放行单
            List<APSTaskStepReleaseBPM> wAPSTaskStepReleaseBPMList = APSTaskStepReleaseBPMDAO.getInstance()
                    .SelectListByOrderList(wLoginUser, wOrderIDList, null, null,
                            wErrorCode);

            // 查询不合格评审放行单
            List<NCRTask> wLetGoNCRTaskList = WDWServiceImpl.getInstance()
                    .NCR_QueryLetGoList(wLoginUser, wOrderIDList, 1).List(NCRTask.class);

            for (int wOrderID : wOrderIDList) {
                for (int wPartID : wPartIDList) {
                    // 无任务，跳过
                    if (wResult.Result.stream().noneMatch(p -> p.OrderID == wOrderID && p.PartID == wPartID)) {
                        continue;
                    }

                    List<APSTaskStepReleaseBPM> wAPSTaskStepReleaseBPM_Part = wAPSTaskStepReleaseBPMList.stream()
                            .filter(p -> p.OrderID == wOrderID
                                    && p.PartID == wPartID && p.Status == 20)
                            .collect(Collectors.toList());
                    List<NCRTask> wLetGoNCRTaskList_Part = wLetGoNCRTaskList.stream()
                            .filter(p -> p.OrderID == wOrderID && p.StationID == wPartID).collect(Collectors.toList());

                    // TableInfo
                    StepPlanTableTemp wTableInfo = new StepPlanTableTemp();
                    wTableInfo.OrderID = wOrderID;
                    wTableInfo.PartID = wPartID;

                    List<Map<String, Object>> wTableMap = new ArrayList<>();
                    Map<String, Object> wHeadMap = new HashMap<>();
                    List<FPCPart> wStationList = new ArrayList<>();

                    List<LFSWorkAreaStation> wWorkAreaStationList = new ArrayList<>();

                    List<APSTaskStepPlan> wTempList = wResult.Result.stream()
                            .filter(p -> p.OrderID == wOrderID && p.PartID == wPartID).collect(Collectors.toList());

                    // 工序排序
                    OrderTempList(wTempList, wPartOrderList);

                    for (APSTaskStepPlan wItem : wTempList) {
                        FPCPart wPart = new FPCPart();
                        if (wStepList.stream().anyMatch(p -> p.ID == wItem.StepID)) {
                            FPCPartPoint wStep = wStepList.stream().filter(p -> p.ID == wItem.StepID).findFirst().get();
                            wPart.ID = wStep.ID;
                            wPart.Name = wStep.Name;
                            wPart.FactoryID = wItem.OrderNum;
                        }
                        wHeadMap.put("Station_" + wItem.StepID, wPart.Name);
                        wStationList.add(wPart);

                        LFSWorkAreaStation wLFSWorkAreaStation = new LFSWorkAreaStation();
                        wLFSWorkAreaStation.StationID = wPart.ID;
                        wLFSWorkAreaStation.StationName = wPart.Name;
                        wWorkAreaStationList.add(wLFSWorkAreaStation);
                    }

                    List<OMSOrder> wOrderList = wTotalOrderList.stream().filter(p -> p.ID == wOrderID)
                            .collect(Collectors.toList());

                    List<APSTaskPart> wTaskPartList = new ArrayList<>();
                    for (APSTaskStepPlan wAPSTaskStepPlan : wResult.Result) {
                        APSTaskPart wAPSTaskPart = new APSTaskPart();
                        wAPSTaskPart.OrderID = wAPSTaskStepPlan.OrderID;
                        wAPSTaskPart.PartID = wAPSTaskStepPlan.StepID;
                        wAPSTaskPart.StartTime = wAPSTaskStepPlan.StartTime;
                        wAPSTaskPart.EndTime = wAPSTaskStepPlan.EndTime;
                        wAPSTaskPart.Status = wAPSTaskStepPlan.Status;
                        wAPSTaskPart.FinishWorkTime = wAPSTaskStepPlan.RealEndTime;
                        wTaskPartList.add(wAPSTaskPart);
                    }

                    if (wHeadMap.size() == 0) {
                        continue;
                    }
                    wTableMap.add(wHeadMap);
                    wTableMap.addAll(APSServiceImpl.getInstance().ChangeToTableByEndTimeAndTip(wOrderList,
                            wTaskPartList,
                            wWorkAreaStationList, wAPSTaskStepReleaseBPM_Part, wLetGoNCRTaskList_Part).Result);

                    List<FPCPart> wNRList = new ArrayList<>();
                    for (FPCPart wFPCPart : wStationList) {
                        if (wNRList.stream().noneMatch(p -> p.ID == wFPCPart.ID)) {
                            wNRList.add(wFPCPart);
                        }
                    }

                    wTableInfo.Data = wTableMap;
                    wTableInfoMap.add(wTableInfo);
                    // OrderColumn
                    StepPlanTableTemp wOrderColumn = new StepPlanTableTemp();
                    wOrderColumn.OrderID = wOrderID;
                    wOrderColumn.PartID = wPartID;
                    wOrderColumn.Data = wNRList;
                    if (wNRList.size() > 0)
                        wOrderColumnMap.add(wOrderColumn);
                }
            }

            // 表格数据返回
            wResult.CustomResult.put("TableInfoList", wTableInfoMap);
            wResult.CustomResult.put("OrderColumn", wOrderColumnMap);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<APSTaskStepPlan>> APS_QueryStepPlanCompare(BMSEmployee wLoginUser, String wOrderIDs,
                                                                         String wPartIDs, int wAPSShiftPeriod) {
        ServiceResult<List<APSTaskStepPlan>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        try {
            wResult = this.AutoCalc(wLoginUser, wOrderIDs, wPartIDs, wAPSShiftPeriod);
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    private ServiceResult<List<APSTaskStepPlan>> AutoCalc(BMSEmployee wLoginUser, String wOrderIDs, String wPartIDs,
                                                          int wAPSShiftPeriod) {
        ServiceResult<List<APSTaskStepPlan>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        try {
            List<Integer> wPartIDList = StringUtils.parseIntList(wPartIDs.split(","));
            if (wPartIDList.size() == 1) {
                wResult = AutoCalcComponentPlan(wLoginUser, wOrderIDs, wPartIDs, wAPSShiftPeriod);
            } else {
                if (APSConstans.mComponentPlanResult == null) {
                    wResult = AutoCalcComponentPlan(wLoginUser, wOrderIDs, wPartIDs, wAPSShiftPeriod);
                    APSConstans.mComponentPlanResult = wResult;
                } else {
                    wResult = APSConstans.mComponentPlanResult;
                    // 自动计算更新缓存数据
                    ExecutorService wES = Executors.newFixedThreadPool(1);
                    wES.submit(() -> {
                        APSConstans.mComponentPlanResult = AutoCalcComponentPlan(wLoginUser, wOrderIDs, wPartIDs,
                                wAPSShiftPeriod);
                    });
                    wES.shutdown();
                }
            }
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    /**
     * 按照订单的顺序排序
     */
    private List<APSTaskStepPlan> OrderResult(List<OMSOrder> wOList, List<APSTaskStepPlan> wAPSTaskStepPlanList) {
        List<APSTaskStepPlan> wResult = new ArrayList<>();
        try {
            if (wAPSTaskStepPlanList == null || wAPSTaskStepPlanList.size() <= 0) {
                return wResult;
            }

            for (OMSOrder wOMSOrder : wOList) {
                List<APSTaskStepPlan> wList = wAPSTaskStepPlanList.stream().filter(p -> p.OrderID == wOMSOrder.ID)
                        .collect(Collectors.toList());
                if (wList.size() > 0) {
                    wResult.addAll(wList);
                }
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> APS_SendSingleMaterial(BMSEmployee wLoginUser, int wBOMID, String wOrders,
                                                         String wItemIDs) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            List<Integer> wOrderIDList = new ArrayList<>();
            String[] wStrs = wOrders.split(",");
            for (String wStr : wStrs) {
                int wID = StringUtils.parseInt(wStr);
                wOrderIDList.add(wID);
            }

            List<Integer> wBOMItemIDList = new ArrayList<>();
            wStrs = wItemIDs.split(",");
            for (String wStr : wStrs) {
                int wID = StringUtils.parseInt(wStr);
                wBOMItemIDList.add(wID);
            }

            APSServiceImpl.getInstance().SendSingleMaterial(wLoginUser, wBOMID, wBOMItemIDList, wOrderIDList);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> MCS_QueryIDByBOMID(BMSEmployee wLoginUser, int wBOMID) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wResult.Result = MCSLogInfoDAO.getInstance().MCS_QueryIDByBOMID(wLoginUser, wBOMID, wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> MCS_QueryIDByBOPID(BMSEmployee wLoginUser, int wBOPID) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wResult.Result = MCSLogInfoDAO.getInstance().MCS_QueryIDByBOPID(wLoginUser, wBOPID, wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<MCSLogInfo> MCS_QueryLogInfo(BMSEmployee wLoginUser, int wID) {
        ServiceResult<MCSLogInfo> wResult = new ServiceResult<>();
        wResult.Result = new MCSLogInfo();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wResult.Result = MCSLogInfoDAO.getInstance().SelectByID(wLoginUser, wID, wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<String> APS_ReSendBOMByIDList(BMSEmployee wLoginUser, List<Integer> wIDList) {
        ServiceResult<String> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            List<APSBOMItem> wList = APSBOMItemDAO.getInstance().SelectByIDList(wLoginUser, wIDList, wErrorCode);

            String wSendSAP = Configuration.readConfigString("isSendSAP", "config/config");

            OMSOrder wOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wList.get(0).OrderID, wErrorCode);

            if (wSendSAP.equals("1")) {
                // ①质量损失的数据分开发送
                List<APSBOMItem> wQualityLossList = wList.stream().filter(p -> p.BOMType == 9)
                        .collect(Collectors.toList());
                List<APSBOMItem> wNormalList = wList.stream().filter(p -> p.BOMType != 9)
                        .collect(Collectors.toList());

                if (wQualityLossList.size() > 0) {
                    // 判断是否已经有质量损失，若没有，用I创建，若有，用U更新
                    boolean wIsExist = SFCBOMTaskDAO.getInstance().IsExistQualityLoss(wLoginUser, wOrder, wErrorCode);
                    int wUpdateType = 2;
                    String wUpChar = "U";
                    if (!wIsExist) {
                        wUpChar = "I";
                        wUpdateType = 1;
                    }

                    // ①推送台车BOM给SAP
                    String wJson = APSBOMUtils.getInstance().ChangeToJson(wQualityLossList, wUpChar);
                    if (StringUtils.isNotEmpty(wJson)) {
                        wResult.Result = SendToSAP(wLoginUser, wJson, wOrder.OrderNo, 0, wOrder, 0,
                                wQualityLossList.stream().map(p -> p.ID).distinct().collect(Collectors.toList()),
                                wUpdateType);
                    }
                }

                if (wNormalList.size() > 0) {
                    // ①推送台车BOM给SAP
                    String wJson = APSBOMUtils.getInstance().ChangeToJson(wNormalList, "U");
                    if (StringUtils.isNotEmpty(wJson)) {
                        wResult.Result = SendToSAP(wLoginUser, wJson, wOrder.OrderNo, 0, wOrder, 0,
                                wNormalList.stream().map(p -> p.ID).distinct().collect(Collectors.toList()), 2);
                    }
                }
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> OMS_SynchronizePartNo(BMSEmployee wLoginUser, int wOrderID) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            OMSOrder wOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wOrderID, wErrorCode);
            if (wOrder == null || wOrder.ID <= 0) {
                wResult.FaultCode += "提示：订单不存在!";
                return wResult;
            }

            SendToSAP(wOrder);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> APS_SynchronizedStepPlan(BMSEmployee wLoginUser, int wPartID, String wOrders) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            String[] wStrs = wOrders.split(",");
            for (String wStr : wStrs) {
                int wOrderID = StringUtils.parseInt(wStr);

                List<APSTaskStep> wTaskStepList = APSTaskStepDAO.getInstance().SelectList(wLoginUser, -1, wOrderID, -1,
                        -1, -1, -1, wPartID, -1, -1, 1, null, null, null, null, wErrorCode);
                List<APSTaskStepPlan> wPlanList = APSTaskStepPlanDAO.getInstance().SelectList(wLoginUser, -1, wOrderID,
                        -1, -1, wPartID, -1, -1, -1, -1, APSShiftPeriod.Week.getValue(), wErrorCode);
                // ①查找删除的工序
                List<APSTaskStepPlan> wDeleteList = wPlanList.stream()
                        .filter(p -> wTaskStepList.stream().noneMatch(q -> q.StepID == p.StepID))
                        .collect(Collectors.toList());
                APSTaskStepPlanDAO.getInstance().DeleteList(wLoginUser, wDeleteList, wErrorCode);
                // ②查找新增的工序
                List<APSTaskStep> wAddedList = wTaskStepList.stream()
                        .filter(p -> wPlanList.stream().noneMatch(q -> q.StepID == p.StepID))
                        .collect(Collectors.toList());
                for (APSTaskStep wAPSTaskStep : wAddedList) {
                    APSTaskStepPlan wPlan = wPlanList.get(0);
                    wPlan.ID = 0;
                    wPlan.StepID = wAPSTaskStep.StepID;
                    wPlan.StartTime = wAPSTaskStep.PlanStartTime;
                    wPlan.EndTime = wAPSTaskStep.PlanEndTime;
                    APSTaskStepPlanDAO.getInstance().Update(wLoginUser, wPlan, wErrorCode);
                }
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<BMSWorkChargeItem>> BMS_QueryWorkChargeItemList(BMSEmployee wLoginUser,
                                                                              int wWorkChargeID) {
        ServiceResult<List<BMSWorkChargeItem>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wResult.Result = BMSWorkChargeItemDAO.getInstance().SelectList(wLoginUser, -1, wWorkChargeID, -1,
                    wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> BMS_DeleteWorkChargeItemList(BMSEmployee wLoginUser, List<BMSWorkChargeItem> wList) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            BMSWorkChargeItemDAO.getInstance().DeleteList(wLoginUser, wList, wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> BMS_SaveWorkChargeItemList(BMSEmployee wLoginUser, List<BMSWorkChargeItem> wList) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            for (BMSWorkChargeItem bmsWorkChargeItem : wList) {
                List<BMSWorkChargeItem> wHisList = BMSWorkChargeItemDAO.getInstance().SelectList(wLoginUser, -1,
                        bmsWorkChargeItem.WorkChargeID, bmsWorkChargeItem.ProductID, wErrorCode);
                if (wHisList.size() > 0) {
                    continue;
                }
                bmsWorkChargeItem.ID = 0;
                if (bmsWorkChargeItem.WorkChargeID <= 0 || bmsWorkChargeItem.ProductID <= 0) {
                    continue;
                }
                BMSWorkChargeItemDAO.getInstance().Update(wLoginUser, bmsWorkChargeItem, wErrorCode);
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<APSTaskStepCancelLog>> APS_QueryTaskStepCancelLogList(BMSEmployee wLoginUser,
                                                                                    int wOrderID, int wPartID,
                                                                                    Calendar wStartTime,
                                                                                    Calendar wEndTime) {
        ServiceResult<List<APSTaskStepCancelLog>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wResult.Result = APSTaskStepCancelLogDAO.getInstance().SelectList(wLoginUser, -1, wOrderID, wPartID, -1, -1,
                    wStartTime, wEndTime, wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> APS_SaveStepCancelLog(BMSEmployee wLoginUser, List<APSTaskStep> wList,
                                                        int wCancelType, String wCancelTypeName, String wRemark) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            if (wList == null || wList.size() <= 0) {
                wResult.FaultCode += "提示：参数错误!";
                return wResult;
            }

            OutResult<Integer> wErrorCode = new OutResult<>(0);

            // ①修改工序任务状态
            for (APSTaskStep wAPSTaskStep : wList) {
                wAPSTaskStep.Status = 5;
                wAPSTaskStep.StartTime = Calendar.getInstance();
                wAPSTaskStep.EndTime = Calendar.getInstance();
                APSTaskStepDAO.getInstance().Update(wLoginUser, wAPSTaskStep, wErrorCode);
                // 删除派工记录
                List<SFCTaskStep> wSFCTaskStepList = SFCTaskStepDAO.getInstance().SelectList(wLoginUser, -1,
                        wAPSTaskStep.ID, -1, -1, -1, null, -1, wErrorCode);
                SFCTaskStepDAO.getInstance().DeleteList(wLoginUser, wSFCTaskStepList, wErrorCode);
                // 禁用派工消息
                for (SFCTaskStep wSFCTaskStep : wSFCTaskStepList) {
                    SFCTaskStepDAO.getInstance().DisableDispatchMessage(wLoginUser, wSFCTaskStep.ID, wErrorCode);
                }
            }

            // ②生成工序任务取消记录
            List<String> wStepNameList = wList.stream().map(p -> p.StepName).distinct().collect(Collectors.toList());
            List<Integer> wStepIDList = wList.stream().map(p -> p.StepID).distinct().collect(Collectors.toList());

            APSTaskStepCancelLog wLog = new APSTaskStepCancelLog(0, wList.get(0).OrderID, wList.get(0).PartNo,
                    wList.get(0).PartID, wList.get(0).PartName, StringUtils.Join(",", wStepIDList),
                    StringUtils.Join(",", wStepNameList), wCancelType, wCancelTypeName, wRemark, wLoginUser.ID,
                    wLoginUser.Name, Calendar.getInstance());
            APSTaskStepCancelLogDAO.getInstance().Update(wLoginUser, wLog, wErrorCode);

            // ③工序全部完工且无后续工位的工位任务需要自动完工
            ExecutorService wES = Executors.newFixedThreadPool(1);
            wES.submit(() -> RPTServiceImpl.getInstance().AutoFinishTaskPart(wLoginUser, wList, wErrorCode));
            wES.shutdown();

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<APSTaskStepCancelLog> APS_QueryTaskStepCancelLogInfo(BMSEmployee wLoginUser, int wID) {
        ServiceResult<APSTaskStepCancelLog> wResult = new ServiceResult<>();
        wResult.Result = new APSTaskStepCancelLog();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wResult.Result = APSTaskStepCancelLogDAO.getInstance().SelectByID(wLoginUser, wID, wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> APS_CancelTaskStepPlan(BMSEmployee wLoginUser, List<APSTaskStep> wDataList) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            if (wDataList == null || wDataList.size() <= 0) {
                return wResult;
            }

            for (APSTaskStep wAPSTaskStep : wDataList) {
                // ②撤销当前工序
                wAPSTaskStep.Status = 1;
                APSTaskStepDAO.getInstance().Update(wLoginUser, wAPSTaskStep, wErrorCode);
                // ①获取后续工序ID集合
                List<Integer> wStepIDList = GetNextStepIDList(wLoginUser, wAPSTaskStep);
                // ③查询后续工序
                for (int wStepID : wStepIDList) {
                    List<APSTaskStep> wList = APSTaskStepDAO.getInstance().SelectList(wLoginUser, -1,
                            wAPSTaskStep.OrderID, -1, wAPSTaskStep.TaskPartID, -1, wAPSTaskStep.LineID,
                            wAPSTaskStep.PartID, wStepID, -1, 1, null, null, null, null, wErrorCode);
                    // ④遍历撤销后续工序
                    for (APSTaskStep apsTaskStep : wList) {
                        apsTaskStep.Status = 1;
                        APSTaskStepDAO.getInstance().Update(wLoginUser, apsTaskStep, wErrorCode);
                    }
                }
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    /**
     * 获取后续工序
     */
    private List<Integer> GetNextStepIDList(BMSEmployee wLoginUser, APSTaskStep wAPSTaskStep) {
        List<Integer> wResult = new ArrayList<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            OMSOrder wOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wAPSTaskStep.OrderID, wErrorCode);
            if (wOrder == null || wOrder.ID <= 0 || wOrder.RouteID <= 0) {
                return wResult;
            }

            List<FPCRoutePartPoint> wRoutePartPointList = FMCServiceImpl.getInstance()
                    .FPC_QueryRoutePartPointListByRouteID(wLoginUser, wOrder.RouteID, wAPSTaskStep.PartID)
                    .List(FPCRoutePartPoint.class);
            wResult = GetNextStepID(wAPSTaskStep.StepID, wRoutePartPointList);
            // 去重
            wResult = wResult.stream().distinct().collect(Collectors.toList());
        } catch (Exception e) {
            logger.error(e.toString());
        }
        return wResult;
    }

    /**
     * 递归获取后续工序
     */
    private List<Integer> GetNextStepID(int wStepID, List<FPCRoutePartPoint> wRoutePartPointList) {
        List<Integer> wResult = new ArrayList<>();
        try {
            // ①前工序等于自己
            if (wRoutePartPointList.stream().anyMatch(p -> p.PrevStepID == wStepID)) {
                List<Integer> wPreveList = wRoutePartPointList.stream().filter(p -> p.PrevStepID == wStepID)
                        .map(p -> p.PartPointID).distinct().collect(Collectors.toList());
                for (Integer wItemID : wPreveList) {
                    if (wResult.stream().noneMatch(p -> p.intValue() == wItemID.intValue())) {
                        wResult.add(wItemID);
                        // ③递归
                        List<Integer> wList = GetNextStepID(wItemID, wRoutePartPointList);
                        for (Integer wID : wList) {
                            if (wResult.stream().noneMatch(p -> p.intValue() == wID.intValue())) {
                                wResult.add(wID);
                            }
                        }
                    }
                }
            }
            // ②后工序map
            if (wRoutePartPointList.stream().anyMatch(p -> p.PartPointID == wStepID)) {
                FPCRoutePartPoint wRoutePartPoint = wRoutePartPointList.stream().filter(p -> p.PartPointID == wStepID)
                        .findFirst().get();
                for (String wItem : wRoutePartPoint.NextStepIDMap.keySet()) {
                    Integer wIntItem = StringUtils.parseInt(wItem);
                    if (wIntItem > 0 && wResult.stream().noneMatch(p -> p.intValue() == wIntItem.intValue())) {
                        wResult.add(wIntItem);
                        // ③递归
                        List<Integer> wList = GetNextStepID(wIntItem, wRoutePartPointList);
                        for (Integer wID : wList) {
                            if (wResult.stream().noneMatch(p -> p.intValue() == wID.intValue())) {
                                wResult.add(wID);
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> APS_ActiveTaskPart(BMSEmployee wLoginUser, int wAPSSchedulingVersionBPMID) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            APSSchedulingVersionBPM wTask = (APSSchedulingVersionBPM) APSSchedulingVersionBPMDAO.getInstance()
                    .BPM_GetTaskInfo(wLoginUser, wAPSSchedulingVersionBPMID, "", wErrorCode);
            for (int wTaskPartID : wTask.TaskPartIDList) {
                APSTaskPart wTaskPart = APSTaskPartDAO.getInstance().SelectByID(wLoginUser, wTaskPartID, wErrorCode);
                if (wTaskPart.Active == 2) {
                    wTaskPart.Active = 1;
                    APSTaskPartDAO.getInstance().Update(wLoginUser, wTaskPart, wErrorCode);
                }
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<APSBomBPM> APS_QueryDefaultBomBPM(BMSEmployee wLoginUser, int wEventID) {
        ServiceResult<APSBomBPM> wResult = new ServiceResult<>();
        wResult.Result = new APSBomBPM();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            List<APSBomBPM> wList = APSBomBPMDAO.getInstance().SelectList(wLoginUser, -1, "", wLoginUser.ID, -1, -1, -1,
                    -1, -1, null, null, new ArrayList<>(Collections.singletonList(0)), wErrorCode);
            if (wList.size() > 0) {
                // APSBomBPMDAO.getInstance().DeleteList(wLoginUser, wList, wErrorCode);
                wResult.Result = wList.get(0);
                wResult.Result.CreateTime = Calendar.getInstance();
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public synchronized ServiceResult<APSBomBPM> APS_CreateBomBPM(BMSEmployee wLoginUser, BPMEventModule wEventID) {
        ServiceResult<APSBomBPM> wResult = new ServiceResult<>();
        wResult.Result = new APSBomBPM();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            // 删除状态为0的单据
            // APSBomBPMDAO.getInstance().DeleteNoUseTask(wLoginUser, wErrorCode);

            wResult.Result.Code = APSBomBPMDAO.getInstance().GetNewCode(wLoginUser, wErrorCode);
            wResult.Result.UpFlowID = wLoginUser.ID;
            wResult.Result.UpFlowName = wLoginUser.Name;
            wResult.Result.CreateTime = Calendar.getInstance();
            wResult.Result.SubmitTime = Calendar.getInstance();
            wResult.Result.ID = 0;
            wResult.Result.Status = APSBomBPMStatus.Default.getValue();
            wResult.Result.StatusText = "";
            wResult.Result.FlowType = wEventID.getValue();

            wResult.Result = (APSBomBPM) APSBomBPMDAO.getInstance().BPM_UpdateTask(wLoginUser, wResult.Result,
                    wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<APSBomBPM> APS_SubmitBomBPM(BMSEmployee wLoginUser, APSBomBPM wData) {
        ServiceResult<APSBomBPM> wResult = new ServiceResult<>();
        wResult.Result = new APSBomBPM();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            if (wData.Status == 20) {
                wData.StatusText = "已完成";
            }

            if (wData.Status == 2) {
                // 删除子项列表
                List<APSBomBPMItem> wSubList = APSBomBPMItemDAO.getInstance().SelectList(wLoginUser, -1, wData.ID, 0,
                        wErrorCode);
                if (wSubList.size() > 0) {
                    APSBomBPMItemDAO.getInstance().DeleteList(wLoginUser, wSubList, wErrorCode);
                }

                wData.APSBomBPMItemList.forEach(p -> p.ID = 0);
            }

            wResult.Result = (APSBomBPM) APSBomBPMDAO.getInstance().BPM_UpdateTask(wLoginUser, wData, wErrorCode);

            // 推送物料
            if (wData.Status == 20) {

                if (wData.Type > 0) {
                    switch (wData.Type) {
                        case 1:// 新增
                            APSBomBPMAdd(wLoginUser, wData, wErrorCode);
                            break;
                        case 2:// 修改
                            APSBomBPMUpdate(wLoginUser, wData, wErrorCode);
                            break;
                        case 3:// 删除
                            APSBomBPMDelete(wLoginUser, wData, wErrorCode);
                            break;
                        default:
                            break;
                    }
                } else {
                    List<APSBomBPMItem> wList = APSBomBPMItemDAO.getInstance().SelectList(wLoginUser, -1, wData.ID, -1,
                            wErrorCode);
                    if (wList == null || wList.size() <= 0) {
                        return wResult;
                    }
                    // 新增
                    List<APSBomBPMItem> wAddList = wList.stream().filter(p -> p.Type == 1).collect(Collectors.toList());
                    // 筛选出修改（新增数量）的数据
                    List<APSBomBPMItem> wUpdateAddList = wList.stream()
                            .filter(p -> p.Type == 2 && p.NewNumber > p.Number).collect(Collectors.toList());
                    // 筛选出修改（减少数量）的数据
                    List<APSBomBPMItem> wUpdateReduceList = wList.stream()
                            .filter(p -> p.Type == 2 && p.NewNumber < p.Number).collect(Collectors.toList());
                    // 筛选出修改（其他变必换）的数据
                    List<APSBomBPMItem> wChangeList = wList.stream().filter(p -> p.Type == 2 && p.NewNumber == p.Number && p.ReplaceType == 0 && p.NewReplaceType > 0).collect(Collectors.toList());

                    APSBomBPMAdd(wLoginUser, wData, wAddList, wUpdateAddList, wUpdateReduceList, wChangeList);
                    // 修改（数量不变、属性变化）
                    List<APSBomBPMItem> wUpdateList = wList.stream().filter(p -> p.Type == 2 && p.NewNumber == p.Number)
                            .collect(Collectors.toList());
                    wUpdateList.removeIf(p -> p.ReplaceType == 0 && p.NewReplaceType > 0);
                    if (wUpdateList.size() > 0) {
                        APSBomBPMUpdate(wLoginUser, wData, wUpdateList);
                    }
                    // 删除
                    List<APSBomBPMItem> wDeleteList = wList.stream().filter(p -> p.Type == 3)
                            .collect(Collectors.toList());
                    if (wDeleteList.size() > 0) {
                        APSBomBPMDelete(wLoginUser, wDeleteList);
                    }

                    // 判断是否推送失败，若无失败信息，则更细单据为推送成功
                    if (wData.SAPStatus != 2) {
                        wData.SAPStatus = 1;
                        wData.SAPStatusText = "推送成功";
                        APSBomBPMDAO.getInstance().Update(wLoginUser, wData, wErrorCode);
                    }
                }
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    /**
     * 新增台车BOM审批推送
     */
    private void APSBomBPMAdd(BMSEmployee wLoginUser, APSBomBPM wData, OutResult<Integer> wErrorCode) {
        try {
            // ①查询子项
            List<APSBomBPMItem> wList = APSBomBPMItemDAO.getInstance().SelectList(wLoginUser, -1, wData.ID, -1,
                    wErrorCode);
            if (wList == null || wList.size() <= 0) {
                return;
            }

            List<APSBOMItem> wAddList = new ArrayList<>();
            // ②遍历新增
            for (APSBomBPMItem wAPSBomBPMItem : wList) {
                APSBOMItem wItem = CloneTool.Clone(wAPSBomBPMItem, APSBOMItem.class);
                wItem.ID = 0;
                wItem.SourceID = wData.ID;
                wItem.SourceType = APSBOMSourceType.BOMAudit.getValue();
                // 若是委外偶修件，需设置为互换件
                if (wAPSBomBPMItem.OutsourceType == 2) {
                    wItem.PartChange = 1;
                }
                wAddList.add(wItem);
            }
            APSServiceImpl.getInstance().APS_UpdateBOMItem(wLoginUser, wAddList);
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    /**
     * 新增台车BOM审批推送
     */
    private void APSBomBPMAdd(BMSEmployee wLoginUser, APSBomBPM wAPSBomBPM, List<APSBomBPMItem> wList,
                              List<APSBomBPMItem> wUpdateAddList, List<APSBomBPMItem> wUpdateReduceList, List<APSBomBPMItem> wChangeList) {
        try {
            wAPSBomBPM.SAPStatus = 0;
            OutResult<Integer> wErrorCode = new OutResult<Integer>(0);
            // ②遍历新增

            List<APSBOMItem> wAddList = new ArrayList<>();


            for (APSBomBPMItem wAPSBomBPMItem : wList) {
                APSBOMItem wItem = CloneTool.Clone(wAPSBomBPMItem, APSBOMItem.class);
                wItem.ID = 0;
                wItem.SourceID = wAPSBomBPMItem.APSBomBPMID;
                wItem.SourceType = APSBOMSourceType.BOMAudit.getValue();
                wItem.AssessmentType = wAPSBomBPMItem.NewAssessmentType;
                wItem.ReplaceType = wAPSBomBPMItem.NewReplaceType;
                wItem.OutsourceType = wAPSBomBPMItem.NewOutsourceType;

                // 若是委外偶修件，需设置为互换件
                if (wAPSBomBPMItem.OutsourceType == 2) {
                    wItem.PartChange = 1;
                }
                wAddList.add(wItem);

            }

            APSServiceImpl.getInstance().APS_UpdateBOMItem(wLoginUser, wAddList);
            List<APSBOMItem> wBOMItemList = new ArrayList<>();
            APSBOMItem wAPSBOMItem;

            for (int i = 0; i < wList.size(); i++) {

                wAPSBOMItem = wAddList.get(i);

                if (wAPSBOMItem.ID > 0 && wAPSBOMItem.OrderNum > 0) {
                    wBOMItemList.add(wAPSBOMItem);
                }
                // 若推送失败，则更新信息
                if (StringUtils.isEmpty(wAPSBOMItem.ErrorCode)) {
                    wAPSBomBPM.SAPStatus = 2;
                    wAPSBomBPM.SAPStatusText = "SAP服务未响应";
                    //APSBomBPMDAO.getInstance().Update(wLoginUser, wAPSBomBPM, wErrorCode);
                    continue;
                }

                if (wAPSBOMItem.ErrorCode.contains("已提台车变更") && wAPSBOMItem.SourceID == wAPSBomBPM.ID) {

                } else if (wAPSBOMItem.ErrorCode.contains("失败") || wAPSBOMItem.ErrorCode.contains("E")) {
                    wAPSBomBPM.SAPStatus = 2;
                    wAPSBomBPM.SAPStatusText = wAPSBOMItem.ErrorCode;
                    // APSBomBPMDAO.getInstance().Update(wLoginUser, wAPSBomBPM, wErrorCode);
                    continue;
                }

            }

            APSServiceImpl.getInstance().APS_BomItemPropertyChange(wLoginUser, wAPSBomBPM.OrderID,
                    wUpdateAddList.stream().map(p -> p.APSBomItemID).distinct().collect(Collectors.toList()), "X", 0);

            wAddList.clear();

            // ③遍历修改（数量新增）
            for (APSBomBPMItem wAPSBomBPMItem : wUpdateAddList) {


                APSBOMItem wItem = CloneTool.Clone(wAPSBomBPMItem, APSBOMItem.class);
                wItem.ID = 0;
                wItem.Number = wAPSBomBPMItem.NewNumber;
                wItem.ReplaceType = wAPSBomBPMItem.NewReplaceType;
                wItem.OutsourceType = wAPSBomBPMItem.NewOutsourceType;
                wItem.PartChange = wAPSBomBPMItem.NewPartChange;
                wItem.QTType = wAPSBomBPMItem.NewQTType;
                wItem.QTItemType = wAPSBomBPMItem.NewQTItemType;
                wItem.AssessmentType = wAPSBomBPMItem.NewAssessmentType;
                wItem.Remark = wAPSBomBPMItem.NewRemark;
                wItem.SourceID = wAPSBomBPMItem.APSBomBPMID;
                wItem.SourceType = APSBOMSourceType.BOMAudit.getValue();

                wAddList.add(wItem);
            }
            APSServiceImpl.getInstance().APS_UpdateBOMItem(wLoginUser, wAddList);

            APSBomBPMItem wAPSBomBPMItemT;
            for (int i = 0; i < wUpdateAddList.size(); i++) {
                wAPSBOMItem = wAddList.get(i);
                wAPSBomBPMItemT = wUpdateAddList.get(i);

                if (wAPSBomBPMItemT.NewNumber > wAPSBOMItem.Number) {
                    APSBOMItem wCloneItem = CloneTool.Clone(wAPSBOMItem, APSBOMItem.class);
                    wCloneItem.Number = wAPSBomBPMItemT.NewNumber - wAPSBomBPMItemT.Number;
                    wBOMItemList.add(wCloneItem);
                }

                // 若推送失败，则更新信息
                if (StringUtils.isEmpty(wAPSBOMItem.ErrorCode)) {
                    wAPSBomBPM.SAPStatus = 2;
                    wAPSBomBPM.SAPStatusText = "SAP服务未响应";
                    // APSBomBPMDAO.getInstance().Update(wLoginUser, wAPSBomBPM, wErrorCode);
                    continue;
                }

                if (wAPSBOMItem.ErrorCode.contains("已提台车变更") && wAPSBOMItem.SourceID == wAPSBomBPM.ID) {

                } else if (wAPSBOMItem.ErrorCode.contains("失败") || wAPSBOMItem.ErrorCode.contains("E")) {
                    wAPSBomBPM.SAPStatus = 2;
                    wAPSBomBPM.SAPStatusText = wAPSBOMItem.ErrorCode;
                    //APSBomBPMDAO.getInstance().Update(wLoginUser, wAPSBomBPM, wErrorCode);
                    continue;
                }

            }
            APSServiceImpl.getInstance().APS_BomItemPropertyChange(wLoginUser, wAPSBomBPM.OrderID,
                    wChangeList.stream().map(p -> p.APSBomItemID).distinct().collect(Collectors.toList()), "X", 0);

            wAddList.clear();

            //③遍历修改（属性变为必换）
            for (APSBomBPMItem wAPSBomBPMItem : wChangeList) {

                // APSServiceImpl.getInstance().APS_BomItemPropertyChange(wLoginUser, wAPSBomBPMItem.APSBomItemID, "X", 0);

                APSBOMItem wItem = CloneTool.Clone(wAPSBomBPMItem, APSBOMItem.class);
                wItem.ID = 0;
                wItem.Number = wAPSBomBPMItem.NewNumber;
                wItem.ReplaceType = wAPSBomBPMItem.NewReplaceType;
                wItem.OutsourceType = wAPSBomBPMItem.NewOutsourceType;
                wItem.PartChange = wAPSBomBPMItem.NewPartChange;
                wItem.QTType = wAPSBomBPMItem.NewQTType;
                wItem.QTItemType = wAPSBomBPMItem.NewQTItemType;
                wItem.AssessmentType = wAPSBomBPMItem.NewAssessmentType;
                wItem.Remark = wAPSBomBPMItem.NewRemark;
                wItem.SourceID = wAPSBomBPMItem.APSBomBPMID;
                wItem.SourceType = APSBOMSourceType.BOMAudit.getValue();

                wAddList.add(wItem);
            }
            APSServiceImpl.getInstance().APS_UpdateBOMItem(wLoginUser, wAddList);


            for (int i = 0; i < wUpdateAddList.size(); i++) {
                wAPSBOMItem = wAddList.get(i);
                wAPSBomBPMItemT = wUpdateAddList.get(i);

                if (wAPSBomBPMItemT.ReplaceType == 0 && wAPSBomBPMItemT.NewReplaceType > 0) {
                    APSBOMItem wCloneItem = CloneTool.Clone(wAPSBOMItem, APSBOMItem.class);
                    wBOMItemList.add(wCloneItem);
                }

                // 若推送失败，则更新信息
                if (StringUtils.isEmpty(wAPSBOMItem.ErrorCode)) {
                    wAPSBomBPM.SAPStatus = 2;
                    wAPSBomBPM.SAPStatusText = "SAP服务未响应";
                    // APSBomBPMDAO.getInstance().Update(wLoginUser, wAPSBomBPM, wErrorCode);
                    continue;
                }

                if (wAPSBOMItem.ErrorCode.contains("已提台车变更") && wAPSBOMItem.SourceID == wAPSBomBPM.ID) {

                } else if (wAPSBOMItem.ErrorCode.contains("失败") || wAPSBOMItem.ErrorCode.contains("E")) {
                    wAPSBomBPM.SAPStatus = 2;
                    wAPSBomBPM.SAPStatusText = wAPSBOMItem.ErrorCode;
                    // APSBomBPMDAO.getInstance().Update(wLoginUser, wAPSBomBPM, wErrorCode);
                    continue;
                }


            }

            APSServiceImpl.getInstance().APS_BomItemPropertyChange(wLoginUser, wAPSBomBPM.OrderID,
                    wChangeList.stream().map(p -> p.APSBomItemID).distinct().collect(Collectors.toList()), "X", 0);

            wAddList.clear();
            // ③遍历修改（数量减少）
            for (APSBomBPMItem wAPSBomBPMItem : wUpdateReduceList) {

                //  APSServiceImpl.getInstance().APS_BomItemPropertyChange(wLoginUser, wAPSBomBPMItem.APSBomItemID, "X", 0);

                APSBOMItem wItem = CloneTool.Clone(wAPSBomBPMItem, APSBOMItem.class);
                wItem.ID = 0;
                wItem.Number = wAPSBomBPMItem.NewNumber;
                wItem.ReplaceType = wAPSBomBPMItem.NewReplaceType;
                wItem.OutsourceType = wAPSBomBPMItem.NewOutsourceType;
                wItem.PartChange = wAPSBomBPMItem.NewPartChange;
                wItem.QTType = wAPSBomBPMItem.NewQTType;
                wItem.QTItemType = wAPSBomBPMItem.NewQTItemType;
                wItem.AssessmentType = wAPSBomBPMItem.NewAssessmentType;
                wItem.Remark = wAPSBomBPMItem.NewRemark;
                wItem.SourceID = wAPSBomBPMItem.APSBomBPMID;
                wItem.SourceType = APSBOMSourceType.BOMAudit.getValue();
                wAddList.add(wItem);
            }
            APSServiceImpl.getInstance().APS_UpdateBOMItem(wLoginUser, wAddList);


            for (int i = 0; i < wUpdateAddList.size(); i++) {
                wAPSBOMItem = wAddList.get(i);
                wAPSBomBPMItemT = wUpdateAddList.get(i);
                //  String wResult = APSServiceImpl.getInstance().APS_UpdateBOMItem(wLoginUser, wItem).Result;

                if (wAPSBomBPMItemT.NewNumber > wAPSBomBPMItemT.Number) {
                    APSBOMItem wCloneItem = CloneTool.Clone(wAPSBOMItem, APSBOMItem.class);
                    wCloneItem.Number = wAPSBomBPMItemT.NewNumber - wAPSBomBPMItemT.Number;
                    wBOMItemList.add(wCloneItem);
                } else if (wAPSBomBPMItemT.NewReplaceType == 1 && wAPSBomBPMItemT.NewAssessmentType.equals("常规新件")) {
                    APSBOMItem wCloneItem = CloneTool.Clone(wAPSBOMItem, APSBOMItem.class);
                    wBOMItemList.add(wCloneItem);
                }
                // 若推送失败，则更新信息
                if (StringUtils.isEmpty(wAPSBOMItem.ErrorCode)) {
                    wAPSBomBPM.SAPStatus = 2;
                    wAPSBomBPM.SAPStatusText = "SAP服务未响应";
                    //APSBomBPMDAO.getInstance().Update(wLoginUser, wAPSBomBPM, wErrorCode);
                    continue;
                }

                if (wAPSBOMItem.ErrorCode.contains("已提台车变更") && wAPSBOMItem.SourceID == wAPSBomBPM.ID) {

                } else if (wAPSBOMItem.ErrorCode.contains("失败") || wAPSBOMItem.ErrorCode.contains("E")) {
                    wAPSBomBPM.SAPStatus = 2;
                    wAPSBomBPM.SAPStatusText = wAPSBOMItem.ErrorCode;
                    // APSBomBPMDAO.getInstance().Update(wLoginUser, wAPSBomBPM, wErrorCode);
                    continue;
                }
            }

            APSBomBPMDAO.getInstance().Update(wLoginUser, wAPSBomBPM, wErrorCode);


            if (wBOMItemList.size() > 0) {
                // 需要处理下，支持多工位的配送
                ExecutorService wES = Executors.newFixedThreadPool(1);
                wES.submit(() -> {
                    List<Integer> wPartIDList = wBOMItemList.stream().map(p -> p.PartID).distinct()
                            .collect(Collectors.toList());

                    // 读取系统配置，只生成配置的相关工位
                    String wOutLLParts = MESSystemConfigDAO.getInstance().SelectValueByKey(wLoginUser,
                            "Out.LL.Parts", wErrorCode);
                    List<Integer> wOutLLPartsList = StringUtils.parseIntList(wOutLLParts.split(","));

                    for (int wPartID : wPartIDList) {
                        List<APSBOMItem> wItemList = wBOMItemList.stream().filter(p -> p.PartID == wPartID)
                                .collect(Collectors.toList());
                        List<APSBOMItem> wCloneItemList = CloneTool.CloneArray(wItemList, APSBOMItem.class);
                        CreatePSD(wLoginUser, wAPSBomBPM, wCloneItemList);
                        // 创建委外领料单
                        boolean wIsSendOutMaterial = Configuration.readConfigString("OutsourcingPlan", "config/config")
                                .equals("1");
                        if (wIsSendOutMaterial) {
                            wItemList = wItemList.stream()
                                    .filter(p -> p.AssessmentType.equals("修复旧件") && (p.OutsourceType == 1 || p.OutsourceType == 2)
                                    ).collect(Collectors.toList());
                            if (wItemList.size() > 0) {
                                if (wOutLLPartsList.stream().anyMatch(p -> p.intValue() == wPartID)
                                        || wOutLLPartsList.size() == 0) {
                                    CreatePSD_Out(wLoginUser, wAPSBomBPM, wItemList);
                                }

                            }
                        }
                    }
                });
                wES.shutdown();
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    /**
     * 创建配送单
     */
    private void CreatePSD(BMSEmployee wLoginUser, APSBomBPM wAPSBomBPM, List<APSBOMItem> wBOMItemList) {
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            OMSOrder wOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wAPSBomBPM.OrderID, wErrorCode);
            Calendar wDate = Calendar.getInstance();
            wDate.set(Calendar.YEAR, 2022);
            wDate.set(Calendar.MONTH, 3);
            wDate.set(Calendar.DATE, 28);
            wDate.set(Calendar.HOUR_OF_DAY, 0);
            wDate.set(Calendar.MINUTE, 0);
            wDate.set(Calendar.SECOND, 0);
            if (wOrder.RealReceiveDate.compareTo(wDate) >= 0) {
                String wMaterialManage = Configuration.readConfigString("materialManage", "config/config");

                if (wMaterialManage.equals("1")) {

                    boolean wIsSendOutMaterial = Configuration.readConfigString("OutsourcingPlan", "config/config")
                            .equals("1");
                    boolean wIsSendRecoilMaterial = Configuration.readConfigString("IsSendRecoilMaterial", "config" +
                            "/config").equals("1");
                    //是否拆分客供料
                    boolean wIsSplitCustomerMaterial = MESSystemConfigDAO.getInstance().SelectValueByKey(wLoginUser,
                            "wms.split.customer.demand", wErrorCode).equals("1");

                    // 委外偶修、委外必修单独推送
                    wBOMItemList
                            .removeIf(p -> (p.OutsourceType == 2 || p.OutsourceType == 1) && p.ReplaceType == 0);
                    if (wBOMItemList.size() <= 0) {
                        return;
                    }

                    //修复旧件不推产线领料
                    wBOMItemList.removeIf(p -> p.AssessmentType.equals("修复旧件"));
                    if (wBOMItemList.size() <= 0) {
                        return;
                    }

                    // 反冲不推送
                    Map<Integer, Integer> wMaterialTypeMap = MRPMaterialPlanDAO.getInstance().GetMaterialTypeMap(
                            wLoginUser,
                            wBOMItemList.stream().map(p -> p.MaterialID).distinct().collect(Collectors.toList()),
                            wErrorCode);
                    if (!wIsSendRecoilMaterial) {
                        List<Integer> wFCList = new ArrayList<>();
                        for (int wMaterialID : wMaterialTypeMap.keySet()) {
                            int wType = wMaterialTypeMap.get(wMaterialID);
                            if (wType == MSSMaterialType.RecoilMaterial.getValue()) {
                                wFCList.add(wMaterialID);
                            }
                        }

                        //拆分反冲料的领料需求
                        List<APSBOMItem> wRecoilList = wBOMItemList.stream().filter(p -> wFCList.stream().anyMatch(q -> q == p.MaterialID)).collect(Collectors.toList());
                        CreatePSD_Recoil(wLoginUser, wAPSBomBPM, wRecoilList);

                        wBOMItemList.removeIf(p -> wFCList.stream().anyMatch(q -> q == p.MaterialID));
                    }

                    if (wBOMItemList.size() <= 0) {
                        return;
                    }

                    //拆分客供料
                    if (wIsSplitCustomerMaterial) {
                        List<APSBOMItem> wCustomerMaterialList = wBOMItemList.stream().filter(p -> p.CustomerMaterial == 1).collect(Collectors.toList());
                        SendToWMS_Customer(wLoginUser, wAPSBomBPM, wCustomerMaterialList);

                        wBOMItemList.removeIf(p -> p.CustomerMaterial == 1);
                        if (wBOMItemList.size() <= 0) {
                            return;
                        }
                    }

                    Calendar wBaseTime = Calendar.getInstance();
                    wBaseTime.set(2000, 0, 1, 0, 0, 0);

                    String wCode = WMSPickDemandDAO.getInstance().GetNewCode(wLoginUser, wErrorCode);
                    Calendar wTime = Calendar.getInstance();

                    Calendar expectTime1 = Calendar.getInstance();
                    expectTime1.set(wTime.get(Calendar.YEAR), wTime.get(Calendar.MONTH), wTime.get(Calendar.DATE), 0,
                            0, 0);

                    Calendar expectTime2 = Calendar.getInstance();
                    expectTime2.set(wTime.get(Calendar.YEAR), wTime.get(Calendar.MONTH), wTime.get(Calendar.DATE), 12,
                            0, 0);

                    String monitorNo = "";
                    String monitor = "";
                    BMSEmployee wUser = WMSPickDemandDAO.getInstance().GetMonitorByPart(wLoginUser,
                            wBOMItemList.get(0).PartID, wErrorCode);
                    if (StringUtils.isNotEmpty(wUser.LoginID)) {
                        monitorNo = wUser.LoginID;
                        monitor = wUser.Name;
                    }

                    OMSOrder wOMSOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wAPSBomBPM.OrderID,
                            wErrorCode);

                    List<Integer> wMaterialIDList = wBOMItemList.stream().map(p -> p.MaterialID).distinct()
                            .collect(Collectors.toList());
                    Map<Integer, Double> wMaterialPackMap = MRPMaterialPlanDAO.getInstance().GetMaterialPackMap(
                            wLoginUser,
                            wMaterialIDList, wErrorCode);
                    // 获取反冲物料列表
                    boolean wIsChangeFQTY = Configuration.readConfigString("IsSendRecoilMaterial", "config/config")
                            .equals("1");

                    WMSPickDemand wWMSPickDemand = new WMSPickDemand(0, "1900",
                            String.valueOf(WMSOrderType.LineOrder.getValue()), wCode, expectTime1, expectTime2,
                            monitorNo,
                            monitor, wAPSBomBPM.ProductID, wAPSBomBPM.ProductNo, wAPSBomBPM.LineID,
                            wAPSBomBPM.LineName, wAPSBomBPM.CustomerID,
                            APSConstans.GetCRMCustomer(wAPSBomBPM.CustomerID).CustomerName,
                            APSConstans.GetCRMCustomer(wAPSBomBPM.CustomerID).CustomerCode, wAPSBomBPM.OrderID,
                            wAPSBomBPM.PartNo,
                            wBOMItemList.get(0).PartID, APSConstans.GetFPCPartName(wBOMItemList.get(0).PartID),
                            APSConstans.GetFPCPart(wBOMItemList.get(0).PartID).Code,
                            "", "", wBaseTime, "", "", wBaseTime, 1, wLoginUser.ID, wLoginUser.Name,
                            Calendar.getInstance(),
                            wOMSOrder.OrderNo, wBaseTime);
                    wWMSPickDemand.SourceType = WMSPickDemandSourceType.APSBOMAudit.getValue();
                    wWMSPickDemand.SourceID = wAPSBomBPM.ID;
                    wWMSPickDemand.SourceCode = wAPSBomBPM.Code;
                    int wDemandID = WMSPickDemandDAO.getInstance().Update(wLoginUser, wWMSPickDemand, wErrorCode);
                    if (wDemandID <= 0) {
                        return;
                    }
                    // ④创建领料需求单明细
                    int wIndex = 1;
                    for (APSBOMItem wAPSBOMItem : wBOMItemList) {

                        double wFQTY = wAPSBOMItem.Number;
                        int wMaterialType = 0;
                        if (wMaterialTypeMap.containsKey(wAPSBOMItem.MaterialID)) {
                            wMaterialType = wMaterialTypeMap.get(wAPSBOMItem.MaterialID);
                        }
                        // 根据最小包装计算需求
                        if (wMaterialPackMap.containsKey(wAPSBOMItem.MaterialID)
                                && wMaterialType == MSSMaterialType.RecoilMaterial.getValue() && wIsChangeFQTY) {
                            double wMinPack = wMaterialPackMap.get(wAPSBOMItem.MaterialID);
                            if (wMinPack > 0) {
                                int wAreaID = APSUtils.getInstance().GetAreaID(wAPSBOMItem.PartID);
                                wFQTY = WMSServiceImpl.getInstance().WMS_GetRealLLNumber(wLoginUser, wMinPack,
                                        wAPSBOMItem.MaterialID, wAPSBOMItem.Number, wAreaID, wErrorCode).Result;
                            }
                        }

                        WMSPickDemandItem wWMSPickDemandItem = new WMSPickDemandItem(0, wDemandID,
                                wAPSBOMItem.MaterialID,
                                wAPSBOMItem.MaterialNo, wAPSBOMItem.MaterialName, wAPSBOMItem.Number, wOMSOrder.OrderNo,
                                wAPSBOMItem.PartPointID,
                                APSConstans.GetFPCPartPoint(wAPSBOMItem.PartPointID).Code.replace("PS-",
                                        ""),
                                APSConstans.GetFPCPartPointName(wAPSBOMItem.PartPointID), String.valueOf(wIndex), "",
                                wAPSBOMItem.ReplaceType, SFCReplaceType.getEnumType(wAPSBOMItem.ReplaceType).getLable(),
                                wAPSBOMItem.OutsourceType,
                                SFCOutSourceType.getEnumType(wAPSBOMItem.OutsourceType).getLable(),
                                wAPSBOMItem.AssessmentType, "", wBaseTime, wWMSPickDemand.PartID, 1, wAPSBOMItem.Number,
                                wAPSBOMItem.OrderNum);
                        wWMSPickDemandItem.FQTY = wFQTY;
                        wWMSPickDemandItem.IsOriDis = wAPSBOMItem.OriginalType == 1 ? "是" : "否";

                        int wItemID = WMSPickDemandItemDAO.getInstance().Update(wLoginUser, wWMSPickDemandItem,
                                wErrorCode);
                        if (wItemID > 0 && wIsSendRecoilMaterial) {
                            WMSServiceImpl.getInstance().WMS_RecoilMaterialUse(wLoginUser, wItemID);
                        }
                        wIndex++;
                    }

                    // ①手动推送
                    String autoSendWMS = Configuration.readConfigString("autoSendWMS", "config/config");
                    if (autoSendWMS.equals("1")) {
                        WMSServiceImpl.getInstance().WMS_ManualPush(wLoginUser, wDemandID);
                    }
                }
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    /**
     * 创建配送单（反冲料）
     */
    private void CreatePSD_Recoil(BMSEmployee wLoginUser, APSBomBPM wAPSBomBPM, List<APSBOMItem> wBOMItemList) {
        try {
            OutResult<Integer> wErrorCode = new OutResult<Integer>(0);
            // ①读取配置，判断是否需要拆分反冲需求
            String wSplit = MESSystemConfigDAO.getInstance().SelectValueByKey(BaseDAO.SysAdmin,
                    "wms.split.recoil.demand", wErrorCode);
            if (StringUtils.isEmpty(wSplit)) {
                logger.info("未配置是否需要拆分反冲需求!");
                return;
            }

            OMSOrder wOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wAPSBomBPM.OrderID, wErrorCode);
            Calendar wDate = Calendar.getInstance();
            wDate.set(Calendar.YEAR, 2022);
            wDate.set(Calendar.MONTH, 3);
            wDate.set(Calendar.DATE, 28);
            wDate.set(Calendar.HOUR_OF_DAY, 0);
            wDate.set(Calendar.MINUTE, 0);
            wDate.set(Calendar.SECOND, 0);
            if (wOrder.RealReceiveDate.compareTo(wDate) >= 0) {
                String wMaterialManage = Configuration.readConfigString("materialManage", "config/config");
                if (wMaterialManage.equals("1")) {
                    if (wBOMItemList.size() <= 0) {
                        return;
                    }

                    Calendar wBaseTime = Calendar.getInstance();
                    wBaseTime.set(2000, 0, 1, 0, 0, 0);

                    String wCode = WMSPickDemandDAO.getInstance().GetNewCode(wLoginUser, wErrorCode);
                    Calendar wTime = Calendar.getInstance();

                    Calendar expectTime1 = Calendar.getInstance();
                    expectTime1.set(wTime.get(Calendar.YEAR), wTime.get(Calendar.MONTH), wTime.get(Calendar.DATE), 0,
                            0, 0);

                    Calendar expectTime2 = Calendar.getInstance();
                    expectTime2.set(wTime.get(Calendar.YEAR), wTime.get(Calendar.MONTH), wTime.get(Calendar.DATE), 12,
                            0, 0);

                    String monitorNo = "";
                    String monitor = "";
                    BMSEmployee wUser = WMSPickDemandDAO.getInstance().GetMonitorByPart(wLoginUser,
                            wBOMItemList.get(0).PartID, wErrorCode);
                    if (StringUtils.isNotEmpty(wUser.LoginID)) {
                        monitorNo = wUser.LoginID;
                        monitor = wUser.Name;
                    }

                    OMSOrder wOMSOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wAPSBomBPM.OrderID,
                            wErrorCode);

                    WMSPickDemand wWMSPickDemand = new WMSPickDemand(0, "1900",
                            String.valueOf(WMSOrderType.RecoilLL.getValue()), wCode, expectTime1, expectTime2,
                            monitorNo,
                            monitor, wAPSBomBPM.ProductID, wAPSBomBPM.ProductNo, wAPSBomBPM.LineID,
                            wAPSBomBPM.LineName, wAPSBomBPM.CustomerID,
                            APSConstans.GetCRMCustomer(wAPSBomBPM.CustomerID).CustomerName,
                            APSConstans.GetCRMCustomer(wAPSBomBPM.CustomerID).CustomerCode, wAPSBomBPM.OrderID,
                            wAPSBomBPM.PartNo,
                            wBOMItemList.get(0).PartID, APSConstans.GetFPCPartName(wBOMItemList.get(0).PartID),
                            APSConstans.GetFPCPart(wBOMItemList.get(0).PartID).Code,
                            "", "", wBaseTime, "", "", wBaseTime, 1, wLoginUser.ID, wLoginUser.Name,
                            Calendar.getInstance(),
                            wOMSOrder.OrderNo, wBaseTime);
                    wWMSPickDemand.SourceType = WMSPickDemandSourceType.APSBOMAudit.getValue();
                    wWMSPickDemand.SourceID = wAPSBomBPM.ID;
                    wWMSPickDemand.SourceCode = wAPSBomBPM.Code;
                    int wDemandID = WMSPickDemandDAO.getInstance().Update(wLoginUser, wWMSPickDemand, wErrorCode);
                    if (wDemandID <= 0) {
                        return;
                    }
                    // ④创建领料需求单明细
                    int wIndex = 1;
                    for (APSBOMItem wAPSBOMItem : wBOMItemList) {
                        double wFQTY = wAPSBOMItem.Number;
                        WMSPickDemandItem wWMSPickDemandItem = new WMSPickDemandItem(0, wDemandID,
                                wAPSBOMItem.MaterialID,
                                wAPSBOMItem.MaterialNo, wAPSBOMItem.MaterialName, wAPSBOMItem.Number, wOMSOrder.OrderNo,
                                wAPSBOMItem.PartPointID,
                                APSConstans.GetFPCPartPoint(wAPSBOMItem.PartPointID).Code.replace("PS-",
                                        ""),
                                APSConstans.GetFPCPartPointName(wAPSBOMItem.PartPointID), String.valueOf(wIndex), "",
                                wAPSBOMItem.ReplaceType, SFCReplaceType.getEnumType(wAPSBOMItem.ReplaceType).getLable(),
                                wAPSBOMItem.OutsourceType,
                                SFCOutSourceType.getEnumType(wAPSBOMItem.OutsourceType).getLable(),
                                wAPSBOMItem.AssessmentType, "", wBaseTime, wWMSPickDemand.PartID, 1, wAPSBOMItem.Number,
                                wAPSBOMItem.OrderNum);
                        wWMSPickDemandItem.FQTY = wFQTY;
                        wWMSPickDemandItem.IsOriDis = wAPSBOMItem.OriginalType == 1 ? "是" : "否";
                        WMSPickDemandItemDAO.getInstance().Update(wLoginUser, wWMSPickDemandItem,
                                wErrorCode);
                        wIndex++;
                    }

                    // ①手动推送
                    String autoSendWMS = Configuration.readConfigString("autoSendWMS", "config/config");
                    if (autoSendWMS.equals("1")) {
                        WMSServiceImpl.getInstance().WMS_ManualPush(wLoginUser, wDemandID);
                    }
                }
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    /**
     * 创建配送单（委外）
     */
    private void CreatePSD_Out(BMSEmployee wLoginUser, APSBomBPM wAPSBomBPM, List<APSBOMItem> wBOMItemList) {
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            OMSOrder wOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wAPSBomBPM.OrderID, wErrorCode);
            Calendar wDate = Calendar.getInstance();
            wDate.set(Calendar.YEAR, 2022);
            wDate.set(Calendar.MONTH, 3);
            wDate.set(Calendar.DATE, 28);
            wDate.set(Calendar.HOUR_OF_DAY, 0);
            wDate.set(Calendar.MINUTE, 0);
            wDate.set(Calendar.SECOND, 0);
            if (wOrder.RealReceiveDate.compareTo(wDate) >= 0) {
                String wMaterialManage = Configuration.readConfigString("materialManage", "config/config");

                if (wMaterialManage.equals("1")) {

                    boolean wIsSendOutMaterial = Configuration.readConfigString("OutsourcingPlan", "config/config")
                            .equals("1");
                    boolean wIsSendRecoilMaterial = Configuration.readConfigString("IsSendRecoilMaterial", "config" +
                            "/config").equals("1");
                    //是否拆分客供料
                    boolean wIsSplitCustomerMaterial = MESSystemConfigDAO.getInstance().SelectValueByKey(wLoginUser,
                            "wms.split.customer.demand", wErrorCode).equals("1");

                    // 委外偶修、委外必修单独推送
                    wBOMItemList
                            .removeIf(p -> (p.OutsourceType == 2 || p.OutsourceType == 1) && p.ReplaceType == 0);
                    if (wBOMItemList.size() <= 0) {
                        return;
                    }

                    // 反冲不推送
                    Map<Integer, Integer> wMaterialTypeMap = MRPMaterialPlanDAO.getInstance().GetMaterialTypeMap(
                            wLoginUser,
                            wBOMItemList.stream().map(p -> p.MaterialID).distinct().collect(Collectors.toList()),
                            wErrorCode);
                    if (!wIsSendRecoilMaterial) {
                        List<Integer> wFCList = new ArrayList<>();
                        for (int wMaterialID : wMaterialTypeMap.keySet()) {
                            int wType = wMaterialTypeMap.get(wMaterialID);
                            if (wType == MSSMaterialType.RecoilMaterial.getValue()) {
                                wFCList.add(wMaterialID);
                            }
                        }

                        //拆分反冲料的领料需求
                        List<APSBOMItem> wRecoilList = wBOMItemList.stream().filter(p -> wFCList.stream().anyMatch(q -> q == p.MaterialID)).collect(Collectors.toList());
                        CreatePSD_Recoil(wLoginUser, wAPSBomBPM, wRecoilList);

                        wBOMItemList.removeIf(p -> wFCList.stream().anyMatch(q -> q == p.MaterialID));
                    }

                    if (wBOMItemList.size() <= 0) {
                        return;
                    }

                    //拆分客供料
                    if (wIsSplitCustomerMaterial) {
                        List<APSBOMItem> wCustomerMaterialList = wBOMItemList.stream().filter(p -> p.CustomerMaterial == 1).collect(Collectors.toList());
                        SendToWMS_Customer(wLoginUser, wAPSBomBPM, wCustomerMaterialList);

                        wBOMItemList.removeIf(p -> p.CustomerMaterial == 1);
                        if (wBOMItemList.size() <= 0) {
                            return;
                        }
                    }

                    Calendar wBaseTime = Calendar.getInstance();
                    wBaseTime.set(2000, 0, 1, 0, 0, 0);

                    String wCode = WMSPickDemandDAO.getInstance().GetNewCode(wLoginUser, wErrorCode);
                    Calendar wTime = Calendar.getInstance();

                    Calendar expectTime1 = Calendar.getInstance();
                    expectTime1.set(wTime.get(Calendar.YEAR), wTime.get(Calendar.MONTH), wTime.get(Calendar.DATE), 0,
                            0, 0);

                    Calendar expectTime2 = Calendar.getInstance();
                    expectTime2.set(wTime.get(Calendar.YEAR), wTime.get(Calendar.MONTH), wTime.get(Calendar.DATE), 12,
                            0, 0);

                    String monitorNo = "";
                    String monitor = "";
                    BMSEmployee wUser = WMSPickDemandDAO.getInstance().GetMonitorByPart(wLoginUser,
                            wBOMItemList.get(0).PartID, wErrorCode);
                    if (StringUtils.isNotEmpty(wUser.LoginID)) {
                        monitorNo = wUser.LoginID;
                        monitor = wUser.Name;
                    }

                    OMSOrder wOMSOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wAPSBomBPM.OrderID,
                            wErrorCode);

                    List<Integer> wMaterialIDList = wBOMItemList.stream().map(p -> p.MaterialID).distinct()
                            .collect(Collectors.toList());
                    Map<Integer, Double> wMaterialPackMap = MRPMaterialPlanDAO.getInstance().GetMaterialPackMap(
                            wLoginUser,
                            wMaterialIDList, wErrorCode);
                    // 获取反冲物料列表
                    boolean wIsChangeFQTY = Configuration.readConfigString("IsSendRecoilMaterial", "config/config")
                            .equals("1");

                    WMSPickDemand wWMSPickDemand = new WMSPickDemand(0, "1900",
                            String.valueOf(WMSOrderType.OutLL.getValue()), wCode, expectTime1, expectTime2,
                            monitorNo,
                            monitor, wAPSBomBPM.ProductID, wAPSBomBPM.ProductNo, wAPSBomBPM.LineID,
                            wAPSBomBPM.LineName, wAPSBomBPM.CustomerID,
                            APSConstans.GetCRMCustomer(wAPSBomBPM.CustomerID).CustomerName,
                            APSConstans.GetCRMCustomer(wAPSBomBPM.CustomerID).CustomerCode, wAPSBomBPM.OrderID,
                            wAPSBomBPM.PartNo,
                            wBOMItemList.get(0).PartID, APSConstans.GetFPCPartName(wBOMItemList.get(0).PartID),
                            APSConstans.GetFPCPart(wBOMItemList.get(0).PartID).Code,
                            "", "", wBaseTime, "", "", wBaseTime, 1, wLoginUser.ID, wLoginUser.Name,
                            Calendar.getInstance(),
                            wOMSOrder.OrderNo, wBaseTime);
                    wWMSPickDemand.SourceType = WMSPickDemandSourceType.APSBOMAudit_Out.getValue();
                    wWMSPickDemand.SourceID = wAPSBomBPM.ID;
                    wWMSPickDemand.SourceCode = wAPSBomBPM.Code;
                    int wDemandID = WMSPickDemandDAO.getInstance().Update(wLoginUser, wWMSPickDemand, wErrorCode);
                    if (wDemandID <= 0) {
                        return;
                    }
                    // ④创建领料需求单明细
                    int wIndex = 1;
                    for (APSBOMItem wAPSBOMItem : wBOMItemList) {

                        double wFQTY = wAPSBOMItem.Number;
                        int wMaterialType = 0;
                        if (wMaterialTypeMap.containsKey(wAPSBOMItem.MaterialID)) {
                            wMaterialType = wMaterialTypeMap.get(wAPSBOMItem.MaterialID);
                        }
                        // 根据最小包装计算需求
                        if (wMaterialPackMap.containsKey(wAPSBOMItem.MaterialID)
                                && wMaterialType == MSSMaterialType.RecoilMaterial.getValue() && wIsChangeFQTY) {
                            double wMinPack = wMaterialPackMap.get(wAPSBOMItem.MaterialID);
                            if (wMinPack > 0) {
                                int wAreaID = APSUtils.getInstance().GetAreaID(wAPSBOMItem.PartID);
                                wFQTY = WMSServiceImpl.getInstance().WMS_GetRealLLNumber(wLoginUser, wMinPack,
                                        wAPSBOMItem.MaterialID, wAPSBOMItem.Number, wAreaID, wErrorCode).Result;
                            }
                        }

                        WMSPickDemandItem wWMSPickDemandItem = new WMSPickDemandItem(0, wDemandID,
                                wAPSBOMItem.MaterialID,
                                wAPSBOMItem.MaterialNo, wAPSBOMItem.MaterialName, wAPSBOMItem.Number, wOMSOrder.OrderNo,
                                wAPSBOMItem.PartPointID,
                                APSConstans.GetFPCPartPoint(wAPSBOMItem.PartPointID).Code.replace("PS-",
                                        ""),
                                APSConstans.GetFPCPartPointName(wAPSBOMItem.PartPointID), String.valueOf(wIndex), "",
                                wAPSBOMItem.ReplaceType, SFCReplaceType.getEnumType(wAPSBOMItem.ReplaceType).getLable(),
                                wAPSBOMItem.OutsourceType,
                                SFCOutSourceType.getEnumType(wAPSBOMItem.OutsourceType).getLable(),
                                wAPSBOMItem.AssessmentType, "", wBaseTime, wWMSPickDemand.PartID, 1, wAPSBOMItem.Number,
                                wAPSBOMItem.OrderNum);
                        wWMSPickDemandItem.FQTY = wFQTY;
                        wWMSPickDemandItem.IsOriDis = wAPSBOMItem.OriginalType == 1 ? "是" : "否";

                        int wItemID = WMSPickDemandItemDAO.getInstance().Update(wLoginUser, wWMSPickDemandItem,
                                wErrorCode);
                        if (wItemID > 0 && wIsSendRecoilMaterial) {
                            WMSServiceImpl.getInstance().WMS_RecoilMaterialUse(wLoginUser, wItemID);
                        }
                        wIndex++;
                    }

                    // ①手动推送
                    String autoSendWMS = Configuration.readConfigString("autoSendWMS", "config/config");
                    if (autoSendWMS.equals("1")) {
                        WMSServiceImpl.getInstance().WMS_ManualPush(wLoginUser, wDemandID);
                    }
                }
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    /**
     * 修改台车bom审批推送
     */
    private void APSBomBPMUpdate(BMSEmployee wLoginUser, APSBomBPM wData, OutResult<Integer> wErrorCode) {
        try {
            // ①查询子项
            List<APSBomBPMItem> wList = APSBomBPMItemDAO.getInstance().SelectList(wLoginUser, -1, wData.ID, -1,
                    wErrorCode);
            if (wList == null || wList.size() <= 0) {
                return;
            }


            APSServiceImpl.getInstance().APS_BomItemPropertyChange(wLoginUser, wData.OrderID,
                    wList.stream().map(p -> p.APSBomItemID).distinct().collect(Collectors.toList()), "X", 0);

            List<APSBOMItem> wAddList = new ArrayList<>();
            // ②遍历修改
            for (APSBomBPMItem wAPSBomBPMItem : wList) {

                APSBOMItem wItem = CloneTool.Clone(wAPSBomBPMItem, APSBOMItem.class);
                wItem.ID = 0;
                wItem.Number = wAPSBomBPMItem.NewNumber;
                wItem.ReplaceType = wAPSBomBPMItem.NewReplaceType;
                wItem.OutsourceType = wAPSBomBPMItem.NewOutsourceType;
                wItem.PartChange = wAPSBomBPMItem.NewPartChange;
                wItem.QTType = wAPSBomBPMItem.NewQTType;
                wItem.QTItemType = wAPSBomBPMItem.NewQTItemType;
                wItem.AssessmentType = wAPSBomBPMItem.NewAssessmentType;
                wItem.Remark = wAPSBomBPMItem.NewRemark;
                wItem.SourceID = wData.ID;
                wItem.SourceType = APSBOMSourceType.BOMAudit.getValue();

                wAddList.add(wItem);

            }
            APSServiceImpl.getInstance().APS_UpdateBOMItem(wLoginUser, wAddList);

        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    /**
     * 修改台车bom审批推送（数量不变、属性变化）
     */
    private void APSBomBPMUpdate(BMSEmployee wLoginUser, APSBomBPM wAPSBomBPM, List<APSBomBPMItem> wList) {
        try {
            wAPSBomBPM.SAPStatus = 0;
            OutResult<Integer> wErrorCode = new OutResult<Integer>(0);


            APSServiceImpl.getInstance().APS_BomItemPropertyChange(wLoginUser, wAPSBomBPM.OrderID,
                    wList.stream().map(p -> p.APSBomItemID).distinct().collect(Collectors.toList()), "X", 0);

            List<APSBOMItem> wAddList = new ArrayList<>();
            // ②遍历修改
            for (APSBomBPMItem wAPSBomBPMItem : wList) {

                // APSServiceImpl.getInstance().APS_BomItemPropertyChange(wLoginUser, wAPSBomBPMItem.APSBomItemID, "X", 0);

                APSBOMItem wItem = CloneTool.Clone(wAPSBomBPMItem, APSBOMItem.class);
                wItem.ID = 0;
                wItem.Number = wAPSBomBPMItem.NewNumber;
                wItem.ReplaceType = wAPSBomBPMItem.NewReplaceType;
                wItem.OutsourceType = wAPSBomBPMItem.NewOutsourceType;
                wItem.PartChange = wAPSBomBPMItem.NewPartChange;
                wItem.QTType = wAPSBomBPMItem.NewQTType;
                wItem.QTItemType = wAPSBomBPMItem.NewQTItemType;
                wItem.AssessmentType = wAPSBomBPMItem.NewAssessmentType;
                wItem.Remark = wAPSBomBPMItem.NewRemark;
                wItem.SourceID = wAPSBomBPMItem.APSBomBPMID;
                wItem.SourceType = APSBOMSourceType.BOMAudit.getValue();

                wAddList.add(wItem);
            }

            APSServiceImpl.getInstance().APS_UpdateBOMItem(wLoginUser, wAddList);

            APSBOMItem wAPSBOMItem;


            for (int i = 0; i < wList.size(); i++) {
                wAPSBOMItem = wAddList.get(i);
                // wAPSBomBPMItemT=wUpdateAddList.get(i);


                // 若推送失败，则更新信息
                if (StringUtils.isEmpty(wAPSBOMItem.ErrorCode)) {
                    wAPSBomBPM.SAPStatus = 2;
                    wAPSBomBPM.SAPStatusText = "SAP服务未响应";
                    //APSBomBPMDAO.getInstance().Update(wLoginUser, wAPSBomBPM, wErrorCode);
                    continue;
                }

                if (wAPSBOMItem.ErrorCode.contains("已提台车变更") && wAPSBOMItem.SourceID == wAPSBomBPM.ID) {

                } else if (wAPSBOMItem.ErrorCode.contains("失败") || wAPSBOMItem.ErrorCode.contains("E")) {
                    wAPSBomBPM.SAPStatus = 2;
                    wAPSBomBPM.SAPStatusText = wAPSBOMItem.ErrorCode;
                    // APSBomBPMDAO.getInstance().Update(wLoginUser, wAPSBomBPM, wErrorCode);
                    continue;
                }

            }
            APSBomBPMDAO.getInstance().Update(wLoginUser, wAPSBomBPM, wErrorCode);
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    /**
     * 删除台车BOM审批推送
     */
    private void APSBomBPMDelete(BMSEmployee wLoginUser, APSBomBPM wData, OutResult<Integer> wErrorCode) {
        try {
            // ①查询子项
            List<APSBomBPMItem> wList = APSBomBPMItemDAO.getInstance().SelectList(wLoginUser, -1, wData.ID, -1,
                    wErrorCode);
            if (wList == null || wList.size() <= 0) {
                return;
            }
            APSServiceImpl.getInstance().APS_BomItemPropertyChange(wLoginUser,wData.OrderID,
                    wList.stream().map(p -> p.APSBomItemID).distinct().collect(Collectors.toList()), "X", 0);

        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    /**
     * 删除台车BOM审批推送
     */
    private void APSBomBPMDelete(BMSEmployee wLoginUser, List<APSBomBPMItem> wList) {
        try {
            OutResult<Integer> wErrorCode = new OutResult<Integer>(0);

            Map<Integer, List<APSBomBPMItem>> collect = wList.stream().collect(Collectors.groupingBy(p -> p.OrderID));

            for (Integer wOrderID : collect.keySet()) {
                APSServiceImpl.getInstance().APS_BomItemPropertyChange(wLoginUser,wOrderID,
                        collect.get(wOrderID).stream().map(p -> p.APSBomItemID).distinct().collect(Collectors.toList()), "X", 0);
            }

            // ②遍历删除
            for (APSBomBPMItem wAPSBomBPMItem : wList) {
                //APSServiceImpl.getInstance().APS_BomItemPropertyChange(wLoginUser, wAPSBomBPMItem.APSBomItemID, "X", 0);

                // 查询物料配送明细
                int wWMSPickDemandItemID = WMSPickDemandItemDAO.getInstance().SelectIDByOrderNum(wLoginUser,
                        wAPSBomBPMItem.OrderID, wAPSBomBPMItem.MaterialID, wAPSBomBPMItem.OrderNum, wErrorCode);
                if (wWMSPickDemandItemID <= 0) {
                    continue;
                }

                // 删除物料配送明细
                WMSPickDemandItem wmsPickDemandItem = WMSPickDemandItemDAO.getInstance().SelectByID(wLoginUser,
                        wWMSPickDemandItemID, wErrorCode);
                wmsPickDemandItem.FQTY = 0;
                wmsPickDemandItem.DeleteFlag = 1;
                wmsPickDemandItem.Status = WMSPickDemandItemStatusNew.Canceled.getValue();
                WMSPickDemandItemDAO.getInstance().Update(wLoginUser, wmsPickDemandItem,
                        wErrorCode);
                WMSServiceImpl.getInstance().WMS_TestUpdatePickDemand(wLoginUser, wmsPickDemandItem.DemandID,
                        String.valueOf(wmsPickDemandItem.ID));
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    @Override
    public ServiceResult<APSBomBPM> APS_GetBomBPM(BMSEmployee wLoginUser, int wID) {
        ServiceResult<APSBomBPM> wResult = new ServiceResult<>();
        wResult.Result = new APSBomBPM();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            if (wID <= 0) {
                return wResult;
            }

            wResult.Result = (APSBomBPM) APSBomBPMDAO.getInstance().BPM_GetTaskInfo(wLoginUser, wID, "", wErrorCode);

            // 查询通知信息
            List<BFCMessage> wList = APSBomBPMDAO.getInstance().SelectNoticeMessage(wLoginUser, wResult.Result.ID,
                    wErrorCode);
            // 获取人员信息
            List<BMSEmployee> wEmployeeList = new ArrayList<>(APSConstans.GetBMSEmployeeList().values());
            // 筛选已激活的人员ID
            List<Integer> wEmployeeIDList = wEmployeeList.stream()
                    .filter(p -> p.Active == 1)
                    .mapToInt(p -> p.ID)
                    .boxed()
                    .collect(Collectors.toList());
            // 筛选已激活的通知消息
            List<BFCMessage> wNoticeList = wList.stream().filter(p -> wEmployeeIDList.contains((int) p.ResponsorID))
                    .collect(Collectors.toList());

            wResult.CustomResult.put("Notice", wNoticeList);

            wResult.Result.APSBomBPMItemList = APSBomBPMItemDAO.getInstance().SelectList(wLoginUser, -1,
                    wResult.Result.ID, -1, wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e + "::ID=" + wID);
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<BPMTaskBase>> APS_QueryBomBPMEmployeeAll(BMSEmployee wLoginUser, int wTagTypes,
                                                                       Calendar wStartTime, Calendar wEndTime) {
        ServiceResult<List<BPMTaskBase>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            switch (TagTypes.getEnumType(wTagTypes)) {
                case Applicant:// 2发起
                    wResult.Result = APSBomBPMDAO.getInstance().BPM_GetSendTaskList(wLoginUser, wLoginUser.ID,
                            wStartTime,
                            wEndTime, wErrorCode);
                    break;
                case Dispatcher:// 1待做
                    wResult.Result = APSBomBPMDAO.getInstance().BPM_GetUndoTaskList(wLoginUser, wLoginUser.ID,
                            wErrorCode);
                    break;
                case Approver:// 4已做
                    wResult.Result = APSBomBPMDAO.getInstance().BPM_GetDoneTaskList(wLoginUser, wLoginUser.ID,
                            wStartTime,
                            wEndTime, wErrorCode);
                    break;
                default:
                    break;
            }

            if (wResult.Result.size() > 0) {
                wResult.Result = wResult.Result.stream().filter(p -> p.Status != 0).collect(Collectors.toList());
            }

            // 排序
            wResult.Result.sort(Comparator.comparing(BPMTaskBase::getCreateTime, Comparator.reverseOrder()));

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<APSBomBPM>> APS_QueryBomBPMHistory(BMSEmployee wLoginUser, int wID, String wCode,
                                                                 int wUpFlowID, int wOrderID, int wLineID,
                                                                 int wProductID, int wCustomerID, int wType,
                                                                 Calendar wStartTime,
                                                                 Calendar wEndTime) {
        ServiceResult<List<APSBomBPM>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            wResult.Result = APSBomBPMDAO.getInstance().SelectList(wLoginUser, -1, wCode, wUpFlowID, wType, wOrderID,
                    wLineID, wProductID, wCustomerID, wStartTime, wEndTime, null, wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<APSBomBPM>> APS_QueryBomBPMEmployeeAllWeb(BMSEmployee wLoginUser, String wCode,
                                                                        int wUpFlowID, int wOrderID, int wLineID,
                                                                        int wProductID, int wCustomerID, int wType,
                                                                        int wStatus,
                                                                        Calendar wStartTime, Calendar wEndTime,
                                                                        String wMaterialName, String wMaterialNo) {
        ServiceResult<List<APSBomBPM>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            switch (wStatus) {
                case 1:
                    wResult.Result.addAll(APSBomBPMDAO.getInstance().SelectList(wLoginUser, -1, wCode, wUpFlowID, wType,
                            wOrderID, wLineID, wProductID, wCustomerID, wStartTime, wEndTime,
                            new ArrayList<>(Arrays.asList(20, 21, 22)), wErrorCode));
                    break;
                case 0:
                    wResult.Result.addAll(APSBomBPMDAO.getInstance().SelectList(wLoginUser, -1, wCode, wUpFlowID, wType,
                            wOrderID, wLineID, wProductID, wCustomerID, wStartTime, wEndTime,
                            new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5)), wErrorCode));
                    break;
                default:
                    wResult.Result.addAll(APSBomBPMDAO.getInstance().SelectList(wLoginUser, -1, wCode, wUpFlowID, wType,
                            wOrderID, wLineID, wProductID, wCustomerID, wStartTime, wEndTime,
                            new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5, 20, 21, 22)), wErrorCode));
                    break;
            }
            wResult.Result.sort((o1, o2) -> o2.SubmitTime.compareTo(o1.SubmitTime));

            // 筛选物料
            if (StringUtils.isNotEmpty(wMaterialNo) || StringUtils.isNotEmpty(wMaterialName)) {
                List<Integer> wTaskIDList = APSBomBPMItemDAO.getInstance().GetIDListByMaterial(wLoginUser, wMaterialNo,
                        wMaterialName, wErrorCode);
                wResult.Result = wResult.Result.stream()
                        .filter(p -> wTaskIDList.stream().anyMatch(q -> q == p.ID))
                        .collect(Collectors.toList());
            }

            if (wResult.Result.size() <= 0 || wStatus == 1) {
                return wResult;
            }

            // 待办数据处理
            List<BPMTaskBase> wBaseList = APSBomBPMDAO.getInstance().BPM_GetUndoTaskList(wLoginUser, wLoginUser.getID(),
                    wErrorCode);
            if (wBaseList == null || wBaseList.size() <= 0) {
                return wResult;
            }
            for (BPMTaskBase wTaskBase : wBaseList) {
                if (!(wTaskBase instanceof APSBomBPM))
                    continue;
                APSBomBPM wIPTStandardBPM = (APSBomBPM) wTaskBase;
                wIPTStandardBPM.TagTypes = TaskQueryType.ToHandle.getValue();
                for (int i = 0; i < wResult.Result.size(); i++) {
                    if (wResult.Result.get(i).ID == wIPTStandardBPM.ID)
                        wResult.Result.set(i, wIPTStandardBPM);
                }
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> APS_AutoSynchronizedBOM(BMSEmployee wLoginUser) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            // ①找到待同步车型、修程、局段
            List<FPCRoute> wFPCRouteList = FPCRouteDAO.getInstance().GetToSynchronizedList(wLoginUser, wErrorCode);
            // ②通过车型、修程、局段获取已进场、维修中且推送成功到ERP过的车辆
            for (FPCRoute wFPCRoute : wFPCRouteList) {
                List<Integer> wOrderIDList = FPCRouteDAO.getInstance().GetMyOrderIDList(wLoginUser, wFPCRoute,
                        wErrorCode);
                if (wOrderIDList == null || wOrderIDList.size() <= 0) {
                    continue;
                }
                // ③通过车型修程局段获取最新的BOMID
                int wMaxBOMID = FPCRouteDAO.getInstance().GetMaxBOMID(wLoginUser, wFPCRoute, wErrorCode);
                if (wMaxBOMID <= 0) {
                    continue;
                }
                // ④对比推送
                for (int wOrderID : wOrderIDList) {

                    MSSBOM wMSSBOM = WMSServiceImpl.getInstance().MSS_QueryBOM(wLoginUser, wMaxBOMID, "", -1)
                            .Info(MSSBOM.class);
                    if (wMSSBOM == null || wMSSBOM.ID <= 0) {
                        continue;
                    }

                    OMSOrder wOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wOrderID, wErrorCode);
                    if (wOrder == null || wOrder.ID <= 0) {
                        continue;
                    }

                    if (wMSSBOM.RouteID != wOrder.RouteID) {
                        continue;
                    }

                    APSServiceImpl.getInstance().APS_AddAPSBOMToSAP(wLoginUser, wMaxBOMID, wOrderID);
                }
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public void APS_HandleBOMOnTime() {
        try {
            Calendar wSTime = Calendar.getInstance();
            wSTime.set(Calendar.getInstance().get(Calendar.YEAR), Calendar.getInstance().get(Calendar.MONTH),
                    Calendar.getInstance().get(Calendar.DATE), 2, 0, 0);
            Calendar wETime = Calendar.getInstance();
            wETime.set(Calendar.getInstance().get(Calendar.YEAR), Calendar.getInstance().get(Calendar.MONTH),
                    Calendar.getInstance().get(Calendar.DATE), 2, 0, 30);

            // 同步台车BOM到ERP
            if (Calendar.getInstance().compareTo(wSTime) > 0 && Calendar.getInstance().compareTo(wETime) < 0) {
                APSServiceImpl.getInstance().APS_AutoSynchronizedBOM(BaseDAO.SysAdmin);
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    @Override
    public synchronized ServiceResult<APSTaskStepCancelLogBPM> APS_QueryDefaultTaskStepCancelLogBPM(
            BMSEmployee wLoginUser, int wEventID) {
        ServiceResult<APSTaskStepCancelLogBPM> wResult = new ServiceResult<>();
        wResult.Result = new APSTaskStepCancelLogBPM();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            List<APSTaskStepCancelLogBPM> wList = APSTaskStepCancelLogBPMDAO.getInstance().SelectList(wLoginUser, -1,
                    "", wLoginUser.ID, -1, -1, null, null, new ArrayList<>(Collections.singletonList(0)), -1,
                    wErrorCode);
            if (wList.size() > 0) {
                wResult.Result = wList.get(0);
                wResult.Result.CreateTime = Calendar.getInstance();
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public synchronized ServiceResult<APSTaskStepCancelLogBPM> APS_CreateTaskStepCancelLogBPM(BMSEmployee wLoginUser,
                                                                                              BPMEventModule wEventID) {
        ServiceResult<APSTaskStepCancelLogBPM> wResult = new ServiceResult<>();
        wResult.Result = new APSTaskStepCancelLogBPM();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wResult.Result.Code = APSTaskStepCancelLogBPMDAO.getInstance().GetNewCode(wLoginUser, wErrorCode);
            wResult.Result.UpFlowID = wLoginUser.ID;
            wResult.Result.UpFlowName = wLoginUser.Name;
            wResult.Result.CreateTime = Calendar.getInstance();
            wResult.Result.SubmitTime = Calendar.getInstance();
            wResult.Result.ID = 0;
            wResult.Result.Status = APSTaskStepCancelLogBPMStatus.Default.getValue();
            wResult.Result.StatusText = "";
            wResult.Result.FlowType = wEventID.getValue();

            wResult.Result = (APSTaskStepCancelLogBPM) APSTaskStepCancelLogBPMDAO.getInstance()
                    .BPM_UpdateTask(wLoginUser, wResult.Result, wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<APSTaskStepCancelLogBPM> APS_SubmitTaskStepCancelLogBPM(BMSEmployee wLoginUser,
                                                                                 APSTaskStepCancelLogBPM wData) {
        ServiceResult<APSTaskStepCancelLogBPM> wResult = new ServiceResult<>();
        wResult.Result = new APSTaskStepCancelLogBPM();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            if (wData.Status == 20) {
                wData.StatusText = "已完成";
                // 取消工序计划
                TaskStepCancel(wLoginUser, wData, wErrorCode);
                // 领料需求单取消
                String materialManage = Configuration.readConfigString("materialManage", "config/config");
                if (materialManage.equals("1")) {

                }
            }

            wResult.Result = (APSTaskStepCancelLogBPM) APSTaskStepCancelLogBPMDAO.getInstance()
                    .BPM_UpdateTask(wLoginUser, wData, wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    private void TaskStepCancel(BMSEmployee wLoginUser, APSTaskStepCancelLogBPM wData, OutResult<Integer> wErrorCode) {
        try {
            if (StringUtils.isEmpty(wData.StepIDs)) {
                return;
            }

            String[] wStrs = wData.StepIDs.split(",");
            List<APSTaskStep> wList = new ArrayList<>();
            for (String wStr : wStrs) {
                int wStepID = StringUtils.parseInt(wStr);
                if (wStepID <= 0) {
                    continue;
                }

                List<APSTaskStep> wItemList = APSTaskStepDAO.getInstance().SelectList(wLoginUser, -1, wData.OrderID, -1,
                        -1, -1, -1, wData.PartID, wStepID, -1, 1, null, null, null, null, wErrorCode);
                if (wItemList != null && wItemList.size() > 0) {
                    wList.addAll(wItemList);
                }
            }

            APSServiceImpl.getInstance().APS_SaveStepCancelLog(wLoginUser, wList, wData.CancelType, "",
                    wData.DescribeInfo);
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }

    @Override
    public ServiceResult<APSTaskStepCancelLogBPM> APS_GetTaskStepCancelLogBPM(BMSEmployee wLoginUser, int wID) {
        ServiceResult<APSTaskStepCancelLogBPM> wResult = new ServiceResult<>();
        wResult.Result = new APSTaskStepCancelLogBPM();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wResult.Result = (APSTaskStepCancelLogBPM) APSTaskStepCancelLogBPMDAO.getInstance()
                    .BPM_GetTaskInfo(wLoginUser, wID, "", wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<BPMTaskBase>> APS_QueryTaskStepCancelLogBPMEmployeeAll(BMSEmployee wLoginUser,
                                                                                     int wTagTypes,
                                                                                     Calendar wStartTime,
                                                                                     Calendar wEndTime) {
        ServiceResult<List<BPMTaskBase>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            switch (TagTypes.getEnumType(wTagTypes)) {
                case Applicant:// 2发起
                    wResult.Result = APSTaskStepCancelLogBPMDAO.getInstance().BPM_GetSendTaskList(wLoginUser,
                            wLoginUser.ID,
                            wStartTime, wEndTime, wErrorCode);
                    break;
                case Dispatcher:// 1待做
                    wResult.Result = APSTaskStepCancelLogBPMDAO.getInstance().BPM_GetUndoTaskList(wLoginUser,
                            wLoginUser.ID,
                            wErrorCode);
                    break;
                case Approver:// 4已做
                    wResult.Result = APSTaskStepCancelLogBPMDAO.getInstance().BPM_GetDoneTaskList(wLoginUser,
                            wLoginUser.ID,
                            wStartTime, wEndTime, wErrorCode);
                    break;
                default:
                    break;
            }

            if (wResult.Result.size() > 0) {
                wResult.Result = wResult.Result.stream().filter(p -> p.Status != 0).collect(Collectors.toList());
            }

            // 排序
            wResult.Result.sort(Comparator.comparing(BPMTaskBase::getCreateTime, Comparator.reverseOrder()));

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<APSTaskStepCancelLogBPM>> APS_QueryTaskStepCancelLogBPMHistory(BMSEmployee wLoginUser,
                                                                                             int wID, String wCode,
                                                                                             int wUpFlowID,
                                                                                             int wOrderID,
                                                                                             int wPartID,
                                                                                             Calendar wStartTime,
                                                                                             Calendar wEndTime) {
        ServiceResult<List<APSTaskStepCancelLogBPM>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            wResult.Result = APSTaskStepCancelLogBPMDAO.getInstance().SelectList(wLoginUser, wUpFlowID, wCode,
                    wUpFlowID, wOrderID, wPartID, wStartTime, wEndTime, null, -1, wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<APSTaskStepCancelLogBPM>> APS_QueryTaskStepCancelLogBPMEmployeeAllWeb(
            BMSEmployee wLoginUser, String wCode, int wUpFlowID, int wOrderID, int wPartID, int wStatus,
            Calendar wStartTime, Calendar wEndTime, int wCancelType) {
        ServiceResult<List<APSTaskStepCancelLogBPM>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            switch (wStatus) {
                case 1:
                    wResult.Result.addAll(APSTaskStepCancelLogBPMDAO.getInstance().SelectList(wLoginUser, -1, "",
                            wUpFlowID,
                            wOrderID, wPartID, wStartTime, wEndTime, new ArrayList<>(Arrays.asList(20, 21, 22)),
                            wCancelType, wErrorCode));
                    break;
                case 0:
                    wResult.Result.addAll(APSTaskStepCancelLogBPMDAO.getInstance().SelectList(wLoginUser, -1, "",
                            wUpFlowID,
                            wOrderID, wPartID, wStartTime, wEndTime, new ArrayList<>(Arrays.asList(1, 2, 3, 4)),
                            wCancelType, wErrorCode));
                    break;
                default:
                    wResult.Result.addAll(APSTaskStepCancelLogBPMDAO.getInstance().SelectList(wLoginUser, -1, "",
                            wUpFlowID,
                            wOrderID, wPartID, wStartTime, wEndTime,
                            new ArrayList<>(Arrays.asList(1, 2, 3, 20, 21, 22)), wCancelType, wErrorCode));
                    break;
            }
            wResult.Result.sort((o1, o2) -> o2.SubmitTime.compareTo(o1.SubmitTime));

            // 翻译取消类型
            for (APSTaskStepCancelLogBPM apsTaskStepCancelLogBPM : wResult.Result) {
                apsTaskStepCancelLogBPM.CancelTypeName = APSTaskStepCancelLogCancelType
                        .getEnumType(apsTaskStepCancelLogBPM.CancelType).getLable();
            }

            if (wResult.Result.size() <= 0 || wStatus == 1) {
                return wResult;
            }

            // 待办数据处理
            List<BPMTaskBase> wBaseList = APSTaskStepCancelLogBPMDAO.getInstance().BPM_GetUndoTaskList(wLoginUser,
                    wLoginUser.getID(), wErrorCode);
            if (wBaseList == null || wBaseList.size() <= 0) {
                return wResult;
            }
            for (BPMTaskBase wTaskBase : wBaseList) {
                if (!(wTaskBase instanceof APSTaskStepCancelLogBPM))
                    continue;
                APSTaskStepCancelLogBPM wIPTStandardBPM = (APSTaskStepCancelLogBPM) wTaskBase;
                wIPTStandardBPM.TagTypes = TaskQueryType.ToHandle.getValue();
                for (int i = 0; i < wResult.Result.size(); i++) {
                    if (wResult.Result.get(i).ID == wIPTStandardBPM.ID)
                        wResult.Result.set(i, wIPTStandardBPM);
                }
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public void APS_BOMTaskToSAP(BMSEmployee wLoginUser, List<SFCBOMTaskItem> wDataList) {
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            SFCBOMTask wTask = (SFCBOMTask) SFCBOMTaskDAO.getInstance().BPM_GetTaskInfo(wLoginUser,
                    wDataList.get(0).SFCBOMTaskID, "", wErrorCode);

            // 禁用之前的台车BOM
            DisableAPSBOM(wLoginUser, wDataList, wTask);

            // 推送给MES和SAP
            SynchronizedToSap(wLoginUser, wTask, wErrorCode, wDataList, wTask.ID);
        } catch (Exception e) {
            logger.error(e.toString());
        }
    }

    /**
     * ID查询
     */
    @Override
    public ServiceResult<APSTriggerPart> APS_QueryTriggerPart(BMSEmployee wLoginUser, int wID) {
        ServiceResult<APSTriggerPart> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            wResult.Result = APSTriggerPartDAO.getInstance().SelectByID(wLoginUser, wID, wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(e.toString());
        }
        return wResult;
    }

    /**
     * 条件查询
     */
    @Override
    public ServiceResult<List<APSTriggerPart>> APS_QueryTriggerPartList(BMSEmployee wLoginUser, int wID, int wProductID,
                                                                        int wLineID, int wCustomerID, int wActive) {
        ServiceResult<List<APSTriggerPart>> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            wResult.Result = APSTriggerPartDAO.getInstance().SelectList(wLoginUser, wID, wProductID, wLineID,
                    wCustomerID, wActive, wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(e.toString());
        }
        return wResult;
    }

    /**
     * 更新或修改
     */
    @Override
    public ServiceResult<Integer> APS_UpdateTriggerPart(BMSEmployee wLoginUser, APSTriggerPart wAPSTriggerPart) {
        ServiceResult<Integer> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            if (wAPSTriggerPart.ID <= 0) {
                List<APSTriggerPart> wList = APSTriggerPartDAO.getInstance().SelectList(wLoginUser, -1,
                        wAPSTriggerPart.ProductID, wAPSTriggerPart.LineID, -1, -1, wErrorCode);
                if (wList.stream().anyMatch(p -> p.PartID == wAPSTriggerPart.PartID)) {
                    wResult.FaultCode += "提示：该工位已添加!";
                    return wResult;
                }
            }

            wResult.Result = APSTriggerPartDAO.getInstance().Update(wLoginUser, wAPSTriggerPart, wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(e.toString());
        }
        return wResult;
    }

    /**
     * 批量激活或禁用
     */
    @Override
    public ServiceResult<Integer> APS_ActiveTriggerPartList(BMSEmployee wLoginUser, List<Integer> wIDList,
                                                            int wActive) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);
            APSTriggerPartDAO.getInstance().Active(wLoginUser, wIDList, wActive, wErrorCode);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<BMSEmployee>> APS_QueryUserByParts(BMSEmployee wLoginUser, String wPartIDs) {
        ServiceResult<List<BMSEmployee>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            if (StringUtils.isEmpty(wPartIDs)) {
                return wResult;
            }

            List<Integer> wUserIDList = APSBomBPMDAO.getInstance().GetUserByParts(wLoginUser, wPartIDs, wErrorCode);
            for (Integer wUserID : wUserIDList) {
                BMSEmployee wUser = APSConstans.GetBMSEmployee(wUserID);
                if (wUser.ID > 0)
                    wResult.Result.add(wUser);
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<MRPMaterialPlan>> MRP_QueryMaterialPlanList(BMSEmployee wLoginUser, int wProductID,
                                                                          int wLineID, int wCustomerID, int wOrderID,
                                                                          int wPartID, int wStepID, String wMaterial,
                                                                          int wMaterialType,
                                                                          int wReplaceType, int wOutSourceType,
                                                                          Calendar wStartTime, Calendar wEndTime) {
        ServiceResult<List<MRPMaterialPlan>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wResult.Result = MRPMaterialPlanDAO.getInstance().SelectList(wLoginUser, -1, wProductID, wLineID,
                    wCustomerID, wOrderID, wPartID, wStepID, -1, "", "", wMaterialType, "", 1, wReplaceType,
                    wOutSourceType, wStartTime, wEndTime, null, null, wMaterial, wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> MRP_HandTrigger(BMSEmployee wLoginUser, int wOrderID, int wPartID) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            List<MRPMaterialPlan> wList = MRPMaterialPlanDAO.getInstance().SelectList(wLoginUser, -1, -1, -1, -1,
                    wOrderID, wPartID, -1, -1, "", "", -1, "", 1, -1, -1, null, null, null, null, "", wErrorCode);
            if (wList.stream().anyMatch(p -> p.Status != MRPMaterialPlanStatus.Save.getValue())) {
                wResult.FaultCode += "提示：当前工位的物料配送单已生成!";
                return wResult;
            }

            this.TriggerMaterialDistributionSheet(wLoginUser, wList, MRPMaterialPlanStatus.HandSubmit.getValue());

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    /**
     * 自动将物料需求计划生成物料配送单
     */
    @Override
    public void APS_AutoCreateDeliveryOrder(BMSEmployee wLoginUser) {
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            // ①查询状态为保存的物料需求计划
            String wMRPMaterialPlanDays = Configuration.readConfigString("mrpmaterialplandays", "config/config");
            int wPlanDays = StringUtils.parseInt(wMRPMaterialPlanDays);
            Calendar wToday = Calendar.getInstance();
            wToday.add(Calendar.DATE, wPlanDays);
            wToday.set(Calendar.HOUR_OF_DAY, 23);
            wToday.set(Calendar.MINUTE, 59);
            wToday.set(Calendar.SECOND, 59);

            boolean wOutsourcingPlan = Configuration.readConfigString("OutsourcingPlan", "config/config").equals(
                    "1");

            List<MRPMaterialPlan> wList = MRPMaterialPlanDAO.getInstance().SelectAutoList(wLoginUser, wToday,
                    wErrorCode);
            // ②遍历，判断是否满足自动推送时间
            for (MRPMaterialPlan wMRPMaterialPlan : wList) {
                List<MRPMaterialPlan> wItemList = MRPMaterialPlanDAO.getInstance().SelectList(wLoginUser, -1, -1, -1,
                        -1, wMRPMaterialPlan.OrderID, wMRPMaterialPlan.PartID, -1, -1, "", "", -1, "", 1, -1, -1, null,
                        null, null, null, "", wErrorCode);
                // ③若满足，自动推送
                this.TriggerMaterialDistributionSheet(wLoginUser, wItemList,
                        MRPMaterialPlanStatus.SystemSubmit.getValue());

                if (wOutsourcingPlan) {
                    // 触发委外必修件物料配送单
                    TriggerMaterialDistributionSheet_Out(BaseDAO.SysAdmin, wItemList,
                            MRPMaterialPlanStatus.SystemSubmit.getValue());
                }
            }
        } catch (Exception e) {
            logger.error(e.toString());
        }
    }

    /**
     * 自动推送物料配送单至WMS
     */
    @Override
    public void APS_AutoSendDemandList(BMSEmployee wLoginUser) {
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            String wSendToWMS = Configuration.readConfigString("sendtowms", "config/config");
            if (!wSendToWMS.equals("1")) {
                return;
            }

            // ①查询状态为保存的物料需求计划
            String wWMSPickDemandDays = Configuration.readConfigString("wmspickdemanddays", "config/config");
            int wPlanDays = StringUtils.parseInt(wWMSPickDemandDays);

            Calendar wToday = Calendar.getInstance();
            wToday.add(Calendar.DATE, wPlanDays);
            wToday.set(Calendar.HOUR_OF_DAY, 23);
            wToday.set(Calendar.MINUTE, 59);
            wToday.set(Calendar.SECOND, 59);

            List<Integer> wList = WMSPickDemandDAO.getInstance().SelectAutoList(wLoginUser, wToday, wErrorCode);
            // ②遍历，判断是否满足自动推送时间
            for (int wWMSPickDemandID : wList) {
                // ③若满足，自动推送
                WMSServiceImpl.getInstance().WMS_ManualPush(wLoginUser, wWMSPickDemandID);
            }
        } catch (Exception e) {
            logger.error(e.toString());
        }
    }

    @Override
    public synchronized ServiceResult<Integer> BPM_CreateToDoMessage(BMSEmployee wLoginUser, int wFlowID, int wTaskID,
                                                                     int wModuleID,
                                                                     String wCode) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            // ①查询流程历史
            List<BPMActivitiHisTask> wNewTaskList = BPMServiceImpl.getInstance()
                    .BPM_GetHistoryInstanceByID(BaseDAO.SysAdmin, wFlowID).List(BPMActivitiHisTask.class);
            if (wNewTaskList == null || wNewTaskList.size() <= 0) {
                return wResult;
            }
            // ②根据StepID查询消息是否已生成
            if (StringUtils.isEmpty(wNewTaskList.get(0).Assignee)) {
                return wResult;
            }
            String[] wStrs = wNewTaskList.get(0).Assignee.split(",");
            int wApplyer = StringUtils.parseInt(wStrs[0]);
            // ③若没生成，生成待办消息
            List<BPMActivitiHisTask> wToTaskList = wNewTaskList.stream().filter(p -> p.Status == 0)
                    .collect(Collectors.toList());
            if (wToTaskList.size() <= 0) {
                return wResult;
            }
            if (StringUtils.isEmpty(wToTaskList.get(0).Assignee)) {
                return wResult;
            }

            Calendar wMinTime = wNewTaskList.stream().min(Comparator.comparing(BPMActivitiHisTask::getStartTime))
                    .get().StartTime;
            Calendar wEndTime = Calendar.getInstance();
            wEndTime.add(Calendar.DATE, 1);

            List<BFCMessage> wBFCMessageListAll = CoreServiceImpl.getInstance().BFC_GetMessageList(wLoginUser, -1,
                    wModuleID,
                    wTaskID, BFCMessageType.Task.getValue(), -1, -1, wMinTime, wEndTime).List(BFCMessage.class);
            wBFCMessageListAll = wBFCMessageListAll.stream().filter(p -> p.Active == BFCMessageStatus.Default.getValue()
                    || p.Active == BFCMessageStatus.Sent.getValue()
                    || p.Active == BFCMessageStatus.Read.getValue()).collect(Collectors.toList());

            List<BFCMessage> wBFCMessageList = new ArrayList<>();
            BFCMessage wMessage;
            for (BPMActivitiHisTask wBPMActivitiHisTask : wToTaskList) {
                int wStepID = StringUtils.parseInt(wBPMActivitiHisTask.ID);
                if (wStepID <= 0) {
                    continue;
                }

                int wShiftID = MESServer.MES_QueryShiftID(wLoginUser.CompanyID, Calendar.getInstance(),
                        APSShiftPeriod.Day,
                        FMCShiftLevel.Day, 0);
                for (String wItem : wBPMActivitiHisTask.Assignee.split(",")) {
                    int wUser = StringUtils.parseInt(wItem);
                    if (wUser <= 0) {
                        continue;
                    }

                    if (wBFCMessageListAll.stream().anyMatch(p -> p.StepID == wStepID && p.ResponsorID == wUser)) {
                        continue;
                    }

                    wMessage = new BFCMessage();
                    wMessage.Active = 0;
                    wMessage.CompanyID = 0;
                    wMessage.CreateTime = Calendar.getInstance();
                    wMessage.EditTime = Calendar.getInstance();
                    wMessage.ID = 0;
                    wMessage.MessageID = wTaskID;
                    wMessage.Title = wCode;
                    wMessage.MessageText = StringUtils.Format("模块：{0} 发起人：{1}  发起时刻：{2} 待{3}",
                                    BPMEventModule.getEnumType(wModuleID).getLable(),
                                    APSConstans.GetBMSEmployeeName(wApplyer),
                                    StringUtils.parseCalendarToString(wBPMActivitiHisTask.StartTime, "yyyy-MM-dd " +
                                            "HH:mm"),
                                    wBPMActivitiHisTask.Name)
                            .trim();
                    wMessage.ModuleID = wModuleID;
                    wMessage.ResponsorID = wUser;
                    wMessage.ShiftID = wShiftID;
                    wMessage.StepID = StringUtils.parseInt(wBPMActivitiHisTask.ID);
                    wMessage.StationID = 0;
                    wMessage.Type = BFCMessageType.Task.getValue();
                    wBFCMessageList.add(wMessage);
                }

            }
            CoreServiceImpl.getInstance().BFC_UpdateMessageList(wLoginUser, wBFCMessageList);
            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<MESMaterialReturn> MES_QueryDefaultMaterialReturn(BMSEmployee wLoginUser, int wEventID,
                                                                           int wTaskID) {
        ServiceResult<MESMaterialReturn> wResult = new ServiceResult<>();
        wResult.Result = new MESMaterialReturn();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            List<MESMaterialReturn> wList = MESMaterialReturnDAO.getInstance().SelectList(wLoginUser, -1,
                    wLoginUser.ID, "",
                    "", -1, -1, -1, -1, -1, new ArrayList<>(Collections.singletonList(0)),
                    null, null, null, null, wErrorCode);
            if (wList.size() > 0) {
                wResult.Result = wList.get(0);
                wResult.Result.FlowType = BPMEventModule.ReturnToWarehouse.getValue();
                wResult.Result.CreateTime = Calendar.getInstance();
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public synchronized ServiceResult<MESMaterialReturn> MES_CreateMaterialReturn(BMSEmployee wLoginUser,
                                                                                  BPMEventModule wEventID) {
        ServiceResult<MESMaterialReturn> wResult = new ServiceResult<>();
        wResult.Result = new MESMaterialReturn();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wResult.Result.Code = MESMaterialReturnDAO.getInstance().GetNewCode(wLoginUser, wErrorCode);
            wResult.Result.UpFlowID = wLoginUser.ID;
            wResult.Result.UpFlowName = wLoginUser.Name;
            wResult.Result.CreateTime = Calendar.getInstance();
            wResult.Result.SubmitTime = Calendar.getInstance();
            wResult.Result.ID = 0;
            wResult.Result.Status = MESMaterialReturnStatus.Default.getValue();
            wResult.Result.StatusText = "";
            wResult.Result.FlowType = wEventID.getValue();

            wResult.Result = (MESMaterialReturn) MESMaterialReturnDAO.getInstance().BPM_UpdateTask(wLoginUser,
                    wResult.Result, wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<MESMaterialReturn> MES_SubmitMaterialReturn(BMSEmployee wLoginUser, MESMaterialReturn wData) {
        ServiceResult<MESMaterialReturn> wResult = new ServiceResult<>();
        wResult.Result = new MESMaterialReturn();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            if (wData.Status == 1) {
                // 删除子表
                List<MESMaterialReturnItem> wItemList = MESMaterialReturnItemDAO.getInstance().SelectList(wLoginUser,
                        -1, wData.ID, -1, -1, "",
                        wErrorCode);
                wItemList.removeIf(p -> wData.ItemList.stream().anyMatch(q -> q.ID == p.ID));
                if (wItemList.size() > 0) {
                    MESMaterialReturnItemDAO.getInstance().DeleteList(wLoginUser, wItemList, wErrorCode);
                }
                // 保存新子表
                for (MESMaterialReturnItem wMESMaterialReturnItem : wData.ItemList) {
                    wMESMaterialReturnItem.ReturnID = wData.ID;
                    MESMaterialReturnItemDAO.getInstance().Update(wLoginUser, wMESMaterialReturnItem, wErrorCode);
                }

                // 保存工位班组长
                String monitorNo = "";
                String monitor = "";
                BMSEmployee wUser = WMSPickDemandDAO.getInstance().GetMonitorByPart(wLoginUser, wData.PartID,
                        wErrorCode);
                if (StringUtils.isNotEmpty(wUser.LoginID)) {
                    monitorNo = wUser.LoginID;
                    monitor = wUser.Name;
                }
                wData.Monitor = monitor;
                wData.MonitorNo = monitorNo;

                // 线程关闭工艺变更退料待办消息
                ExecutorService wES = Executors.newFixedThreadPool(1);
                wES.submit(() -> MESMaterialReturnItemDAO.getInstance().CloseTechMessage(wLoginUser, wData.OrderID,
                        wData.TechChangeID, wData.ItemList.get(0).PartPointID, wErrorCode));
                wES.shutdown();

                // 查询BOM类型，赋值
                wData.BOMType = MESMaterialReturnDAO.getInstance().QueryBOMType(wLoginUser, wData.OrderID,
                        wData.ItemList.get(0).DemandItemID, wErrorCode);
            } else if (wData.Status == 2) {
                // 保存新子表
                for (MESMaterialReturnItem wMESMaterialReturnItem : wData.ItemList) {
                    MESMaterialReturnItemDAO.getInstance().Update(wLoginUser, wMESMaterialReturnItem, wErrorCode);
                }
            }
            // 推送WMS
            if (wData.Status == MESMaterialReturnStatus.Finished.getValue()) {
                wData.StatusText = "已申请退料";
                List<MESMaterialReturnItem> wItemList = MESMaterialReturnItemDAO.getInstance().SelectList(wLoginUser,
                        -1, wData.ID, -1, -1, "", wErrorCode);
                OMSOrder wOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wData.OrderID, wErrorCode);
                WMSLinePartTLs wWMSLinePartTLs = MESMaterialReturnDAO.getInstance().GetWMSLinePartTLs(wData, wItemList);

                if (wWMSLinePartTLs.header.get(0).details == null
                        || wWMSLinePartTLs.header.get(0).details.size() <= 0) {
                    wData.StatusText = "已完成";
                } else {
                    WMSReturn wReturn = MyHelperServiceImpl.getInstance().WMS_PostTL(wWMSLinePartTLs, wData, wOrder);
                    if (wReturn.returnFlag.equals("1")) {
                        wData.StatusText = "待入库";
                        wData.SendStatus = 1;
                        wData.SendDesc = "推送成功";
                    } else {
                        wData.StatusText = "申请退料失败";
                        wData.SendStatus = 2;
                        wData.SendDesc = wReturn.returnDesc;
                    }
                }
            }

            wResult.Result = (MESMaterialReturn) MESMaterialReturnDAO.getInstance().BPM_UpdateTask(wLoginUser, wData,
                    wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<MESMaterialReturn> MES_GetMaterialReturn(BMSEmployee wLoginUser, int wID) {
        ServiceResult<MESMaterialReturn> wResult = new ServiceResult<>();
        wResult.Result = new MESMaterialReturn();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wResult.Result = (MESMaterialReturn) MESMaterialReturnDAO.getInstance().BPM_GetTaskInfo(wLoginUser, wID, "",
                    wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<BPMTaskBase>> MES_QueryMaterialReturnEmployeeAll(BMSEmployee wLoginUser, int wTagTypes,
                                                                               Calendar wStartTime, Calendar wEndTime) {
        ServiceResult<List<BPMTaskBase>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            switch (TagTypes.getEnumType(wTagTypes)) {
                case Applicant:// 2发起
                    wResult.Result = MESMaterialReturnDAO.getInstance().BPM_GetSendTaskList(wLoginUser, wLoginUser.ID,
                            wStartTime, wEndTime, wErrorCode);
                    break;
                case Dispatcher:// 1待做
                    wResult.Result = MESMaterialReturnDAO.getInstance().BPM_GetUndoTaskList(wLoginUser, wLoginUser.ID,
                            wErrorCode);
                    break;
                case Approver:// 4已做
                    wResult.Result = MESMaterialReturnDAO.getInstance().BPM_GetDoneTaskList(wLoginUser, wLoginUser.ID,
                            wStartTime, wEndTime, wErrorCode);
                    break;
                default:
                    break;
            }

            if (wResult.Result.size() > 0) {
                wResult.Result = wResult.Result.stream().filter(p -> p.Status != 0).collect(Collectors.toList());
            }

            // 排序
            wResult.Result.sort(Comparator.comparing(BPMTaskBase::getCreateTime, Comparator.reverseOrder()));

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> APS_ReCreatePSD(BMSEmployee wLoginUser, int wSFCBomTaskID) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            SFCBOMTask wSFCBOMTask = (SFCBOMTask) SFCBOMTaskDAO.getInstance().BPM_GetTaskInfo(wLoginUser,
                    wSFCBomTaskID, "",
                    wErrorCode);
            if (wSFCBOMTask == null || wSFCBOMTask.ID <= 0) {
                return wResult;
            }

            List<APSBOMItem> wList = new ArrayList<>();
            for (SFCBOMTaskItem wSFCBOMTaskItem : wSFCBOMTask.SFCBOMTaskItemList) {
                int wAPSBOMID = APSBOMItemDAO.getInstance().SelectIDBySource(wLoginUser, wSFCBOMTaskItem.ID,
                        wErrorCode);
                if (wAPSBOMID > 0) {
                    APSBOMItem apsbomItem = APSBOMItemDAO.getInstance().SelectByID(wLoginUser, wAPSBOMID, wErrorCode);
                    if (apsbomItem != null && apsbomItem.ID > 0) {
                        wList.add(apsbomItem);
                    }
                }
            }

            CreatePSD(wLoginUser, wList, wSFCBomTaskID, wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<WMSPickDemand>> WMS_QueryOutEmployeeAll(BMSEmployee wLoginUser, int wTagType,
                                                                      Calendar wStartTime, Calendar wEndTime) {
        ServiceResult<List<WMSPickDemand>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            switch (wTagType) {
                case 1:
                    wResult.Result = WMSPickDemandDAO.getInstance().SelectList(wLoginUser, -1,
                            "200", "", -1, -1, -1, "", -1, 2, null, null, null, wErrorCode);
                    break;
                case 2:
                    wResult.Result = WMSPickDemandDAO.getInstance().SelectList(wLoginUser, -1, "200", "", -1, -1, -1,
                            "", -1, 3, wStartTime, wEndTime, null, wErrorCode);
                    break;
                default:
                    break;
            }
            wResult.Result = wResult.Result.stream().filter(p -> p.CreateID == wLoginUser.ID)
                    .collect(Collectors.toList());

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> APS_ReCreatePSD_BOMAudit(BMSEmployee wLoginUser, int wAPSBomAuditID) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            APSBomBPM wAPSBomBPM = (APSBomBPM) APSBomBPMDAO.getInstance().BPM_GetTaskInfo(wLoginUser,
                    wAPSBomAuditID, "",
                    wErrorCode);
            if (wAPSBomBPM == null || wAPSBomBPM.ID <= 0) {
                return wResult;
            }

            List<APSBomBPMItem> wList = APSBomBPMItemDAO.getInstance().SelectList(wLoginUser, -1, wAPSBomBPM.ID, -1,
                    wErrorCode);
            if (wList == null || wList.size() <= 0) {
                return wResult;
            }
            // 新增
            List<APSBomBPMItem> wAddList = wList.stream().filter(p -> p.Type == 1).collect(Collectors.toList());
            // 筛选出修改（新增数量）的数据
            List<APSBomBPMItem> wUpdateAddList = wList.stream().filter(p -> p.Type == 2 && p.NewNumber > p.Number)
                    .collect(Collectors.toList());
            // 筛选出修改（减少数量）的数据
            List<APSBomBPMItem> wUpdateReduceList = wList.stream()
                    .filter(p -> p.Type == 2 && p.NewNumber < p.Number)
                    .collect(Collectors.toList());
            // 筛选出修改（其他属性变必换）的数据
            List<APSBomBPMItem> wChangeList = wList.stream().filter(p -> p.Type == 2 && p.NewNumber == p.Number && p.ReplaceType == 0 && p.NewReplaceType == 1).collect(Collectors.toList());

            APSBomBPMAdd(wLoginUser, wAPSBomBPM, wAddList, wUpdateAddList, wUpdateReduceList, wChangeList);
            // 修改
            List<APSBomBPMItem> wUpdateList = wList.stream().filter(p -> p.Type == 2 && p.NewNumber == p.Number)
                    .collect(Collectors.toList());
            wUpdateList.removeIf(p -> p.ReplaceType == 0 && p.NewReplaceType == 1);
            if (wUpdateList.size() > 0) {
                APSBomBPMUpdate(wLoginUser, wAPSBomBPM, wUpdateList);
            }
            // 删除
            List<APSBomBPMItem> wDeleteList = wList.stream().filter(p -> p.Type == 3)
                    .collect(Collectors.toList());
            if (wDeleteList.size() > 0) {
                APSBomBPMDelete(wLoginUser, wDeleteList);
            }

            // 更新推送状态
            if (wAPSBomBPM.SAPStatus != 2) {
                wAPSBomBPM.SAPStatus = 1;
                wAPSBomBPM.SAPStatusText = "推送成功";
                APSBomBPMDAO.getInstance().Update(wLoginUser, wAPSBomBPM, wErrorCode);
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> WMS_UpdatePickDemandItem(BMSEmployee wLoginUser, WMSPickDemandItem wItem) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wResult.Result = WMSPickDemandItemDAO.getInstance().Update(wLoginUser, wItem, wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> APS_DeleteBOMList(BMSEmployee wLoginUser, int wOrderID) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            List<Integer> wBOMIDList = APSBOMItemDAO.getInstance().SelectRepeatList(wLoginUser, wOrderID, wErrorCode);
            if (wBOMIDList == null || wBOMIDList.size() == 0) {
                return wResult;
            }

            List<APSBOMItem> wBOMList = APSBOMItemDAO.getInstance().SelectByIDList(wLoginUser, wBOMIDList,
                    wErrorCode);
            for (APSBOMItem wAPSBOMItem : wBOMList) {
                APSServiceImpl.getInstance().APS_DeleteBOMItem(wLoginUser, wAPSBOMItem);
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<String> APS_ExportNotSameData(BMSEmployee wLoginUser) {
        ServiceResult<String> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            MyExcelSheet wMyExcelSheet = WMSPickDemandDAO.getInstance().GetMyExcelSheet();

            List<MyExcelSheet> wMyExcelSheetList = new ArrayList<>(Collections.singletonList(wMyExcelSheet));

            wResult.Result = ExcelUtil.ExportData(wMyExcelSheetList, "需求计划不一致的配送单");

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> APS_BackNotStart(BMSEmployee wLoginUser, int wTaskStepID) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            // ①状态改为下达
            APSTaskStep wAPSTaskStep = APSTaskStepDAO.getInstance().SelectByID(wLoginUser, wTaskStepID, wErrorCode);
            if (wAPSTaskStep == null || wAPSTaskStep.ID <= 0) {
                return wResult;
            }
            wAPSTaskStep.Status = 2;
            // ②更新工序任务
            APSTaskStepDAO.getInstance().Update(wLoginUser, wAPSTaskStep, wErrorCode);

            ExecutorService wES = Executors.newFixedThreadPool(1);
            wES.submit(() -> {
                // 禁用自检、互检、专检、预检消息
                Map<Integer, Integer> wTaskIPTMap = APSTaskStepDAO.getInstance().SelectTaskIPTIDListByTaskStepID(
                        wLoginUser, wTaskStepID,
                        wErrorCode);
                for (int wTaskIPTID : wTaskIPTMap.keySet()) {
                    int wTaskType = wTaskIPTMap.get(wTaskIPTID);
                    BFCMessageDAO.getInstance().CloseMessage(wLoginUser, wTaskIPTID, wTaskType, wErrorCode);
                }
                // ③禁用相关检验任务
                APSTaskStepDAO.getInstance().DisableRelaTaskIPT(wLoginUser, wAPSTaskStep.ID, wErrorCode);
                // ④派工任务状态改为未开始
                APSTaskStepDAO.getInstance().StartSFCTaskStep(wLoginUser, wAPSTaskStep.ID, wErrorCode);
                // ⑤派工消息状态改为0
                List<SFCTaskStep> wSFCTaskStepList = SFCTaskStepDAO.getInstance().SelectList(wLoginUser, -1,
                        wAPSTaskStep.ID,
                        -1, -1, -1, null, -1, wErrorCode);
                for (SFCTaskStep wSFCTaskStep : wSFCTaskStepList) {
                    APSTaskStepDAO.getInstance().StartSFCTaskStepMessage(wLoginUser, wSFCTaskStep.ID, wErrorCode);
                }
            });
            wES.shutdown();

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> APS_PickDemandByDifPlan(BMSEmployee wLoginUser, String wDemandNo) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            // ①获取配送单
            List<WMSPickDemand> wWMSPickDemandList = WMSPickDemandDAO.getInstance().SelectList(wLoginUser, -1, "",
                    wDemandNo, -1, -1,
                    -1, "", -1, -1, null, null, null, wErrorCode);
            if (wWMSPickDemandList == null || wWMSPickDemandList.size() == 0) {
                return wResult;
            }
            WMSPickDemand wWMSPickDemand0 = wWMSPickDemandList.get(0);
            // ②获取配送单明细
            List<WMSPickDemandItem> wWMSPickDemandItemList = WMSPickDemandItemDAO.getInstance().SelectList(wLoginUser,
                    -1, wWMSPickDemand0.ID, -1, "", -1, wErrorCode);
            if (wWMSPickDemandItemList == null || wWMSPickDemandItemList.size() == 0) {
                return wResult;
            }
            // ②获取需求计划
            List<MRPMaterialPlan> wMRPMaterialPlanList = MRPMaterialPlanDAO.getInstance().SelectList(wLoginUser, -1, -1,
                    -1, -1, wWMSPickDemand0.OrderID,
                    wWMSPickDemand0.PartID, -1, -1, "", "", -1, "", 1,
                    -1, -1, null, null, null, null, "", wErrorCode);
            if (wMRPMaterialPlanList == null || wMRPMaterialPlanList.size() == 0) {
                return wResult;
            }
            // ③遍历需求计划，找到配送单中不存在的差异项
            List<MRPMaterialPlan> wNotExsitList = wMRPMaterialPlanList.stream()
                    .filter(p -> wWMSPickDemandItemList.stream().noneMatch(q -> q.PartPointID == p.StepID
                            && q.MaterialID == p.MaterialID && q.ReplaceType == p.ReplaceType
                            && q.OutSourceType == p.OutSourceType))
                    .collect(Collectors.toList());
            if (wNotExsitList.size() <= 0) {
                return wResult;
            }
            // ④查询订单
            OMSOrder wOMSOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wWMSPickDemand0.OrderID, wErrorCode);
            if (wOMSOrder == null || wOMSOrder.ID <= 0) {
                return wResult;
            }
            // ④创建配送单
            Calendar wBaseTime = Calendar.getInstance();
            wBaseTime.set(2000, 0, 1, 0, 0, 0);

            String wCode = WMSPickDemandDAO.getInstance().GetNewCode(wLoginUser, wErrorCode);
            Calendar wTime = wNotExsitList.get(0).DemandDate;

            Calendar expectTime1 = Calendar.getInstance();
            expectTime1.set(wTime.get(Calendar.YEAR), wTime.get(Calendar.MONTH), wTime.get(Calendar.DATE), 0, 0, 0);

            Calendar expectTime2 = Calendar.getInstance();
            expectTime2.set(wTime.get(Calendar.YEAR), wTime.get(Calendar.MONTH), wTime.get(Calendar.DATE), 12, 0, 0);

            String monitorNo = "";
            String monitor = "";
            BMSEmployee wUser = WMSPickDemandDAO.getInstance().GetMonitorByPart(wLoginUser, wNotExsitList.get(0).PartID,
                    wErrorCode);
            if (StringUtils.isNotEmpty(wUser.LoginID)) {
                monitorNo = wUser.LoginID;
                monitor = wUser.Name;
            }

            WMSPickDemand wWMSPickDemand = new WMSPickDemand(0, "1900",
                    String.valueOf(WMSOrderType.LineOrder.getValue()), wCode, expectTime1, expectTime2, monitorNo,
                    monitor, wNotExsitList.get(0).ProductID,
                    APSConstans.GetFPCProductNo(wNotExsitList.get(0).ProductID),
                    wNotExsitList.get(0).LineID, APSConstans.GetFMCLineName(wNotExsitList.get(0).LineID),
                    wNotExsitList.get(0).CustomerID,
                    APSConstans.GetCRMCustomer(wNotExsitList.get(0).CustomerID).CustomerName,
                    APSConstans.GetCRMCustomer(wNotExsitList.get(0).CustomerID).CustomerCode,
                    wNotExsitList.get(0).OrderID,
                    wNotExsitList.get(0).PartNo, wNotExsitList.get(0).PartID,
                    APSConstans.GetFPCPartName(wNotExsitList.get(0).PartID),
                    APSConstans.GetFPCPart(wNotExsitList.get(0).PartID).Code, "", "", wBaseTime, "", "", wBaseTime, 1,
                    wLoginUser.ID, wLoginUser.Name, Calendar.getInstance(), wNotExsitList.get(0).WBSNo, wBaseTime);
            wWMSPickDemand.SourceType = WMSPickDemandSourceType.Plan.getValue();
            int wDemandID = WMSPickDemandDAO.getInstance().Update(wLoginUser, wWMSPickDemand, wErrorCode);
            if (wDemandID <= 0) {
                return wResult;
            }
            // ④创建领料需求单明细
            int wIndex = 1;

            List<Integer> wMaterialIDList = wNotExsitList.stream()
                    .filter(p -> p.MaterialType == MSSMaterialType.RecoilMaterial.getValue()).map(p -> p.MaterialID)
                    .distinct().collect(Collectors.toList());

            boolean wIsSendRecoilMaterial = Configuration.readConfigString("IsSendRecoilMaterial", "config/config")
                    .equals(
                            "1");

            // 获取物料最小包装字典
            Map<Integer, Double> wMaterialPackMap = MRPMaterialPlanDAO.getInstance().GetMaterialPackMap(wLoginUser,
                    wMaterialIDList, wErrorCode);

            // 获取配套属性
            Map<Integer, String> wMaterialMatchMap = MRPMaterialPlanDAO.getInstance()
                    .GetMaterialMatchMap(BaseDAO.SysAdmin, wMaterialIDList, wErrorCode);

            for (MRPMaterialPlan wMRPMaterialPlan : wNotExsitList) {
                double wFQTY = wMRPMaterialPlan.FQTY;
                // 根据最小包装计算需求
                if (wMaterialPackMap.containsKey(wMRPMaterialPlan.MaterialID)) {
                    double wMinPack = wMaterialPackMap.get(wMRPMaterialPlan.MaterialID);
                    if (wMinPack > 0) {
                        int wAreaID = APSUtils.getInstance().GetAreaID(wMRPMaterialPlan.PartID);
                        wFQTY = WMSServiceImpl.getInstance().WMS_GetRealLLNumber(wLoginUser, wMinPack,
                                wMRPMaterialPlan.MaterialID, wMRPMaterialPlan.FQTY, wAreaID, wErrorCode).Result;
                    }
                }

                // 获取配套属性
                String wGroup = "";
                if (wMaterialMatchMap.containsKey(wMRPMaterialPlan.MaterialID)) {
                    wGroup = wMaterialMatchMap.get(wMRPMaterialPlan.MaterialID);
                }

                WMSPickDemandItem wWMSPickDemandItem = new WMSPickDemandItem(0, wDemandID,
                        wMRPMaterialPlan.MaterialID, wMRPMaterialPlan.MaterialNo, wMRPMaterialPlan.MaterialName,
                        wFQTY, wOMSOrder.OrderNo, wMRPMaterialPlan.StepID,
                        APSConstans.GetFPCPartPoint(wMRPMaterialPlan.StepID).Code.replace("PS-", ""),
                        APSConstans.GetFPCPartPointName(wMRPMaterialPlan.StepID), String.valueOf(wIndex), wGroup,
                        wMRPMaterialPlan.ReplaceType,
                        SFCReplaceType.getEnumType(wMRPMaterialPlan.ReplaceType).getLable(),
                        wMRPMaterialPlan.OutSourceType,
                        SFCOutSourceType.getEnumType(wMRPMaterialPlan.OutSourceType).getLable(),
                        wMRPMaterialPlan.AssessmentType, "", wBaseTime, wWMSPickDemand.PartID,
                        wMRPMaterialPlan.MaterialType, wMRPMaterialPlan.FQTY, wMRPMaterialPlan.BOMItemNum);
                int wItemID = WMSPickDemandItemDAO.getInstance().Update(wLoginUser, wWMSPickDemandItem, wErrorCode);
                wWMSPickDemandItem.IsOriDis = wMRPMaterialPlan.OriginalType == 1 ? "是" : "否";

                if (wItemID > 0 && wIsSendRecoilMaterial && wWMSPickDemandItem.FQTY <= 0) {
                    WMSServiceImpl.getInstance().WMS_RecoilMaterialUse(wLoginUser, wItemID);
                }
                wIndex++;
            }
            // ⑤创建配送明细
            // ⑥保存

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> WMS_UpdatePickDemandItemList(BMSEmployee wLoginUser,
                                                               List<WMSPickDemandItem> wItemList) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wItemList.forEach(p -> WMSPickDemandItemDAO.getInstance().Update(wLoginUser, p, wErrorCode));

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<BMSEmployee>> APS_QueryUserListByPartID(BMSEmployee wLoginUser, int wPartID) {
        ServiceResult<List<BMSEmployee>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            List<FMCWorkCharge> wFMCWorkChargeList = APSConstans.GetFMCWorkChargeList().stream()
                    .filter(p -> p.StationID == wPartID && p.Active == 1).collect(Collectors.toList());
            wResult.Result = APSConstans.GetBMSEmployeeList().values().stream()
                    .filter(p -> wFMCWorkChargeList.stream().anyMatch(q -> q.ClassID == p.DepartmentID))
                    .collect(Collectors.toList());

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> APS_IssueWeekPlan(BMSEmployee wLoginUser, int wWeekPlanID) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            APSSchedulingVersionBPM wData = (APSSchedulingVersionBPM) APSSchedulingVersionBPMDAO.getInstance()
                    .BPM_GetTaskInfo(wLoginUser,
                            wWeekPlanID, "", wErrorCode);

            APSSchedulingVersion wScheduling = APSSchedulingVersionDAO.getInstance().SelectByVersionNo(wLoginUser,
                    wData.VersionNo, wErrorCode);
            if (wScheduling != null && wScheduling.ID > 0) {
                if (wData.APSShiftPeriod == APSShiftPeriod.Week.getValue()) {
                    wScheduling.APSTaskPartList = APSTaskPartDAO.getInstance().SelectListByIDList(wLoginUser,
                            wScheduling.TaskPartIDList, wErrorCode);

                    String materialManage = Configuration.readConfigString("materialManage", "config/config");
                    if (materialManage.equals("1")) {
                        // 触发物料需求计划
                        ExecutorService wES1 = Executors.newFixedThreadPool(1);
                        wES1.submit(() -> APS_TriggerMRP(wLoginUser, wData, wScheduling));
                        wES1.shutdown();
                    }
                }
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> WMS_PickDemandConfirmItemAll(BMSEmployee wLoginUser,
                                                               List<WMSPickDemandItem> wItemList) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            WMSPickDemand wWMSPickDemand = WMSPickDemandDAO.getInstance().SelectByID(wLoginUser,
                    wItemList.get(0).DemandID, wErrorCode);
            if (wWMSPickDemand == null || wWMSPickDemand.ID <= 0) {
                return wResult;
            }

            if (StringUtils.isEmpty(wWMSPickDemand.WaveNumber)) {
                for (WMSPickDemandItem wWMSPickDemandItem : wItemList) {
                    WMSPickDemandItemDAO.getInstance().UpdateIsConfirm(wLoginUser, wWMSPickDemandItem, wErrorCode);
                }
            } else {
                for (WMSPickDemandItem wWMSPickDemandItem : wItemList) {
                    WMSPickDemandItemDAO.getInstance().UpdateIsConfirm(wLoginUser, wWMSPickDemandItem, wErrorCode);
                }
                // 其他单据相同物料也需同样处理
                ExecutorService wES = Executors.newFixedThreadPool(1);
                wES.submit(() -> {
                    List<WMSPickDemand> wList = WMSPickDemandDAO.getInstance().SelectListByWaveNumber(wLoginUser,
                            wWMSPickDemand.WaveNumber, wErrorCode);
                    for (WMSPickDemand wTask : wList) {
                        List<WMSPickDemandItem> wmsPickDemandItems = WMSPickDemandItemDAO.getInstance().SelectList(
                                wLoginUser, -1, wTask.ID, -1,
                                "", -1, wErrorCode);
                        for (WMSPickDemandItem wmsPickDemandItem : wmsPickDemandItems) {
                            if (wItemList.stream().noneMatch(p -> p.PartPointID == wmsPickDemandItem.PartPointID
                                    && p.MaterialNo.equals(wmsPickDemandItem.MaterialNo))) {
                                continue;
                            }
                            WMSPickDemandItem wmsPickDemandItem1 = wItemList.stream()
                                    .filter(p -> p.PartPointID == wmsPickDemandItem.PartPointID
                                            && p.MaterialNo.equals(wmsPickDemandItem.MaterialNo))
                                    .findFirst().get();
                            wmsPickDemandItem.IsConfirmed = wmsPickDemandItem1.IsConfirmed;
                            WMSPickDemandItemDAO.getInstance().UpdateIsConfirm(wLoginUser, wmsPickDemandItem,
                                    wErrorCode);
                        }
                    }
                });
                wES.shutdown();
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<APSTaskStep>> APS_QueryTaskStepListByTime_V2(BMSEmployee wLoginUser,
                                                                           Calendar wStartTime, Calendar wEndTime) {
        ServiceResult<List<APSTaskStep>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            List<SFCTaskStep> wSFCTaskStepList = SFCTaskStepDAO.getInstance().SelectList(wLoginUser, wLoginUser.ID,
                    wStartTime,
                    wEndTime, wErrorCode);
            if (wSFCTaskStepList.size() <= 0) {
                return wResult;
            }

            List<Integer> wTaskStepIDList = wSFCTaskStepList.stream().map(p -> p.TaskStepID).distinct()
                    .collect(Collectors.toList());
            wResult.Result = APSTaskStepDAO.getInstance().SelectListByIDList(wLoginUser, wTaskStepIDList, wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> APS_TriggerTaskStepByFPCRoutePartPoint(BMSEmployee wLoginUser, int wOrderID,
                                                                         int wRoutePartPointID, int wPartID,
                                                                         int wPartPointID) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            List<APSTaskPart> wAPSTaskPartList = APSTaskPartDAO.getInstance().SelectList(wLoginUser, -1, wOrderID, -1,
                    -1, wPartID, 1, APSShiftPeriod.Week.getValue(), null, -1, null, null, wErrorCode);
            if (wAPSTaskPartList == null || wAPSTaskPartList.size() <= 0) {
                return wResult;
            }

            // 查询日计划
            List<APSTaskStep> wAPSTaskStepList = APSTaskStepDAO.getInstance().SelectList(wLoginUser, -1, wOrderID, -1,
                    -1, -1, -1, wPartID, wPartPointID, -1, 1, null, null, null, null, wErrorCode);
            if (wAPSTaskStepList.size() <= 0) {
                // 查询工艺工序
                OMSOrder wOMSOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wOrderID, wErrorCode);
                FPCRoutePartPoint wFPCRoutePartPoint = FMCServiceImpl.getInstance()
                        .FPC_QueryRoutePartPointByID(wLoginUser,
                                wRoutePartPointID)
                        .Info(FPCRoutePartPoint.class);
                // APS
                int wShiftID = MESServer.MES_QueryShiftID(wLoginUser.CompanyID, Calendar.getInstance(),
                        APSShiftPeriod.Day,
                        FMCShiftLevel.Day, 0);
                Calendar wBaseTime = Calendar.getInstance();
                wBaseTime.set(2000, 0, 1, 0, 0, 0);

                APSTaskPart wAPSTaskPart = wAPSTaskPartList.get(0);
                if (wFPCRoutePartPoint != null && wFPCRoutePartPoint.ID > 0) {
                    APSTaskStep wAPSTaskStep = new APSTaskStep();
                    wAPSTaskStep.Active = 1;
                    wAPSTaskStep.ID = 0;
                    wAPSTaskStep.LineID = wAPSTaskPart.LineID;
                    wAPSTaskStep.MaterialNo = wAPSTaskPart.MaterialNo;
                    wAPSTaskStep.OrderID = wAPSTaskPart.OrderID;
                    wAPSTaskStep.PartID = wAPSTaskPart.PartID;
                    wAPSTaskStep.PartNo = wAPSTaskPart.PartNo;
                    wAPSTaskStep.PlanerID = wLoginUser.ID;
                    wAPSTaskStep.ProductNo = wAPSTaskPart.ProductNo;
                    wAPSTaskStep.ShiftID = wShiftID;
                    wAPSTaskStep.Status = APSTaskStatus.Issued.getValue();
                    wAPSTaskStep.StepID = wFPCRoutePartPoint.PartPointID;
                    wAPSTaskStep.TaskPartID = wAPSTaskPart.ID;
                    wAPSTaskStep.TaskLineID = wAPSTaskPart.TaskLineID;
                    wAPSTaskStep.TaskText = wAPSTaskPart.TaskText;
                    wAPSTaskStep.WorkHour = 0;
                    wAPSTaskStep.WorkShopID = wAPSTaskPart.WorkShopID;
                    wAPSTaskStep.StartTime = wBaseTime;
                    wAPSTaskStep.EndTime = wBaseTime;
                    wAPSTaskStep.ReadyTime = wBaseTime;
                    wAPSTaskStep.CreateTime = Calendar.getInstance();
                    wAPSTaskStep.PartPointType = wFPCRoutePartPoint.PartPointType;
                    wAPSTaskStep.FQTY = wFPCRoutePartPoint.TargetNum;
                    wAPSTaskStep.MaterialNoNew = wFPCRoutePartPoint.MaterialNo_S;
                    wAPSTaskStep.PlanStartTime = Calendar.getInstance();
                    wAPSTaskStep.PlanEndTime = Calendar.getInstance();
                    wResult.Result = APSTaskStepDAO.getInstance().Update(wLoginUser, wAPSTaskStep, wErrorCode);
                }
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> WMS_ResendWMS(BMSEmployee wLoginUser, int wSFCBOMTaskID) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            SFCBOMTask wSFCBOMTask = (SFCBOMTask) SFCBOMTaskDAO.getInstance().BPM_GetTaskInfo(wLoginUser,
                    wSFCBOMTaskID, "",
                    wErrorCode);
            wSFCBOMTask.SFCBOMTaskItemList.removeIf(p -> p.Status == 2);
            List<Integer> wMaterialIDList = wSFCBOMTask.SFCBOMTaskItemList.stream().map(p -> p.MaterialID).distinct()
                    .collect(Collectors.toList());
            if (wMaterialIDList.size() <= 0) {
                return wResult;
            }

            List<Integer> wAPSBOMItemIDLIst = SFCBOMTaskDAO.getInstance().SelectAPSBOMItemIDList(wLoginUser,
                    wMaterialIDList, wSFCBOMTask, wErrorCode);
            if (wAPSBOMItemIDLIst.size() <= 0) {
                return wResult;
            }

            List<APSBOMItem> wAPSBOMItemList = APSBOMItemDAO.getInstance().SelectByIDList(wLoginUser, wAPSBOMItemIDLIst,
                    wErrorCode);
            wAPSBOMItemList.forEach(p -> {
                p.NewSourceID = wSFCBOMTask.ID;
                p.NewSourceCode = wSFCBOMTask.Code;
            });
            CreatePSD(wLoginUser, wAPSBOMItemList, wSFCBOMTaskID, wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<APSTaskStepReleaseBPM>> APS_QueryTaskStepReleaseBPMHistory(BMSEmployee wLoginUser,
                                                                                         int wID, String wCode,
                                                                                         int wUpFlowID, int wOrderID,
                                                                                         int wPartID,
                                                                                         Calendar wStartTime,
                                                                                         Calendar wEndTime) {
        ServiceResult<List<APSTaskStepReleaseBPM>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            wResult.Result = APSTaskStepReleaseBPMDAO.getInstance().SelectList(wLoginUser, wUpFlowID, wCode,
                    wUpFlowID, wOrderID, wPartID, wStartTime, wEndTime, null, -1, wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<BPMTaskBase>> APS_QueryTaskStepReleaseBPMEmployeeAll(BMSEmployee wLoginUser,
                                                                                   int wTagTypes, Calendar wStartTime, Calendar wEndTime) {
        ServiceResult<List<BPMTaskBase>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            switch (TagTypes.getEnumType(wTagTypes)) {
                case Applicant:// 2发起
                    wResult.Result = APSTaskStepReleaseBPMDAO.getInstance().BPM_GetSendTaskList(wLoginUser,
                            wLoginUser.ID,
                            wStartTime, wEndTime, wErrorCode);
                    break;
                case Dispatcher:// 1待做
                    wResult.Result = APSTaskStepReleaseBPMDAO.getInstance().BPM_GetUndoTaskList(wLoginUser,
                            wLoginUser.ID,
                            wErrorCode);
                    break;
                case Approver:// 4已做
                    wResult.Result = APSTaskStepReleaseBPMDAO.getInstance().BPM_GetDoneTaskList(wLoginUser,
                            wLoginUser.ID,
                            wStartTime, wEndTime, wErrorCode);
                    break;
                default:
                    break;
            }

            if (wResult.Result.size() > 0) {
                wResult.Result = wResult.Result.stream().filter(p -> p.Status != 0).collect(Collectors.toList());
            }

            // 排序
            wResult.Result.sort(Comparator.comparing(BPMTaskBase::getCreateTime, Comparator.reverseOrder()));

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<APSTaskStepReleaseBPM>> APS_QueryTaskStepReleaseBPMEmployeeAllWeb(BMSEmployee wLoginUser,
                                                                                                String wCode,
                                                                                                int wUpFlowID,
                                                                                                int wOrderID,
                                                                                                int wPartID,
                                                                                                int wStatus,
                                                                                                Calendar wStartTime,
                                                                                                Calendar wEndTime,
                                                                                                int wCancelType) {
        ServiceResult<List<APSTaskStepReleaseBPM>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            switch (wStatus) {
                case 1:
                    wResult.Result.addAll(APSTaskStepReleaseBPMDAO.getInstance().SelectList(wLoginUser, -1, "",
                            wUpFlowID,
                            wOrderID, wPartID, wStartTime, wEndTime, new ArrayList<>(Arrays.asList(20, 21, 22)),
                            wCancelType, wErrorCode));
                    break;
                case 0:
                    wResult.Result.addAll(APSTaskStepReleaseBPMDAO.getInstance().SelectList(wLoginUser, -1, "",
                            wUpFlowID,
                            wOrderID, wPartID, wStartTime, wEndTime, new ArrayList<>(Arrays.asList(1, 2, 3, 4)),
                            wCancelType, wErrorCode));
                    break;
                default:
                    wResult.Result.addAll(APSTaskStepReleaseBPMDAO.getInstance().SelectList(wLoginUser, -1, "",
                            wUpFlowID,
                            wOrderID, wPartID, wStartTime, wEndTime,
                            new ArrayList<>(Arrays.asList(1, 2, 3, 20, 21, 22)), wCancelType, wErrorCode));
                    break;
            }
            wResult.Result.sort((o1, o2) -> o2.SubmitTime.compareTo(o1.SubmitTime));

            if (wResult.Result.size() <= 0 || wStatus == 1) {
                return wResult;
            }

            // 待办数据处理
            List<BPMTaskBase> wBaseList = APSTaskStepReleaseBPMDAO.getInstance().BPM_GetUndoTaskList(wLoginUser,
                    wLoginUser.getID(), wErrorCode);
            if (wBaseList == null || wBaseList.size() <= 0) {
                return wResult;
            }
            for (BPMTaskBase wTaskBase : wBaseList) {
                if (!(wTaskBase instanceof APSTaskStepReleaseBPM))
                    continue;
                APSTaskStepReleaseBPM wIPTStandardBPM = (APSTaskStepReleaseBPM) wTaskBase;
                wIPTStandardBPM.TagTypes = TaskQueryType.ToHandle.getValue();
                for (int i = 0; i < wResult.Result.size(); i++) {
                    if (wResult.Result.get(i).ID == wIPTStandardBPM.ID)
                        wResult.Result.set(i, wIPTStandardBPM);
                }
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<APSTaskStepReleaseBPM> APS_GetTaskStepReleaseBPM(BMSEmployee wLoginUser, int wID) {
        ServiceResult<APSTaskStepReleaseBPM> wResult = new ServiceResult<>();
        wResult.Result = new APSTaskStepReleaseBPM();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wResult.Result = (APSTaskStepReleaseBPM) APSTaskStepReleaseBPMDAO.getInstance()
                    .BPM_GetTaskInfo(wLoginUser, wID, "", wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult APS_QueryDefaultTaskStepReleaseBPM(BMSEmployee wLoginUser, int value) {
        ServiceResult<APSTaskStepReleaseBPM> wResult = new ServiceResult<>();
        wResult.Result = new APSTaskStepReleaseBPM();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            List<APSTaskStepReleaseBPM> wList = APSTaskStepReleaseBPMDAO.getInstance().SelectList(wLoginUser, -1,
                    "", wLoginUser.ID, -1, -1, null, null, new ArrayList<>(Collections.singletonList(0)), -1,
                    wErrorCode);
            if (wList.size() > 0) {
                wResult.Result = wList.get(0);
                wResult.Result.CreateTime = Calendar.getInstance();
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult APS_CreateTaskStepReleaseBPM(BMSEmployee wLoginUser, BPMEventModule wEventID) {
        ServiceResult<APSTaskStepReleaseBPM> wResult = new ServiceResult<>();
        wResult.Result = new APSTaskStepReleaseBPM();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wResult.Result.Code = APSTaskStepReleaseBPMDAO.getInstance().GetNewCode(wLoginUser, wErrorCode);
            wResult.Result.UpFlowID = wLoginUser.ID;
            wResult.Result.UpFlowName = wLoginUser.Name;
            wResult.Result.CreateTime = Calendar.getInstance();
            wResult.Result.SubmitTime = Calendar.getInstance();
            wResult.Result.ID = 0;
            wResult.Result.Status = APSTaskStepCancelLogBPMStatus.Default.getValue();
            wResult.Result.StatusText = "";
            wResult.Result.FlowType = wEventID.getValue();

            wResult.Result = (APSTaskStepReleaseBPM) APSTaskStepReleaseBPMDAO.getInstance()
                    .BPM_UpdateTask(wLoginUser, wResult.Result, wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult APS_SubmitTaskStepReleaseBPM(BMSEmployee wLoginUser, APSTaskStepReleaseBPM wData) {
        ServiceResult<APSTaskStepReleaseBPM> wResult = new ServiceResult<>();
        wResult.Result = new APSTaskStepReleaseBPM();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            if (wData.Status == 20) {
                wData.StatusText = "已完成";
                // 工序放行任务完成后 你后台发个传阅消息到对应的检验员、流程引擎不配置了
                List<BMSWorkCharge> wBMSWorkChargeList = CoreServiceImpl.getInstance()
                        .FMC_QueryWorkChargeList(wLoginUser).List(BMSWorkCharge.class);
                if (wBMSWorkChargeList != null && wBMSWorkChargeList.size() > 0) {
                    wBMSWorkChargeList = wBMSWorkChargeList.stream()
                            .filter(p -> p.Active == 1 && p.StationID == wData.PartID).collect(Collectors.toList());
                    List<Integer> wUserIDList = new ArrayList<>();
                    for (BMSWorkCharge wBMSWorkCharge : wBMSWorkChargeList) {
                        for (int wUserID : wBMSWorkCharge.CheckerList) {
                            if (wUserIDList.stream().anyMatch(p -> p == wUserID)) {
                                continue;
                            }
                            wUserIDList.add(wUserID);
                        }
                    }

                    List<BFCMessage> wBFCMessageList = new ArrayList<>();
                    BFCMessage wMessage = null;
                    int wShiftID = MESServer.MES_QueryShiftID(wLoginUser.CompanyID, Calendar.getInstance(),
                            APSShiftPeriod.Day, FMCShiftLevel.Day, 0);
                    for (int wUserID : wUserIDList) {
                        // 发送任务消息到人员
                        wMessage = new BFCMessage();
                        wMessage.Active = 0;
                        wMessage.CompanyID = 0;
                        wMessage.CreateTime = Calendar.getInstance();
                        wMessage.EditTime = Calendar.getInstance();
                        wMessage.ID = 0;
                        wMessage.MessageID = wData.ID;
                        wMessage.Title = wData.Code;
                        wMessage.MessageText = StringUtils.Format("模块：{0} 发起人：{1} 发起时刻：{2}  {3}已审批，请知晓。",
                                BPMEventModule.APSTaskStepRelease.getLable(),
                                wData.UpFlowName,
                                StringUtils.parseCalendarToString(wData.CreateTime, "yyyy-MM-dd HH:mm"),
                                wLoginUser.Name);
                        wMessage.ModuleID = BPMEventModule.APSTaskStepRelease.getValue();
                        wMessage.ResponsorID = wUserID;
                        wMessage.ShiftID = wShiftID;
                        wMessage.StationID = 0;
                        wMessage.Type = BFCMessageType.Notify.getValue();
                        wBFCMessageList.add(wMessage);
                    }
                    CoreServiceImpl.getInstance().BFC_UpdateMessageList(wLoginUser, wBFCMessageList);
                }
            } else if (wData.Status == 22) {
                wData.StatusText = "已驳回";
            }

            wResult.Result = (APSTaskStepReleaseBPM) APSTaskStepReleaseBPMDAO.getInstance()
                    .BPM_UpdateTask(wLoginUser, wData, wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<Map<String, Object>>> ChangeToTableByRelease(List<OMSOrder> wOrderList,
                                                                           List<APSTaskPart> wAPSTaskPartList,
                                                                           List<LFSWorkAreaStation> wStationList,
                                                                           List<APSTaskStepReleaseBPM> wAPSTaskStepReleaseBPMList, List<NCRTask> wLetGoNCRTaskList) {
        ServiceResult<List<Map<String, Object>>> wResult = new ServiceResult<>();
        try {
            if (wOrderList == null || wAPSTaskPartList == null || wStationList == null) {
                wResult.FaultCode += "参数不合法 转换Table失败！";
                return wResult;
            }
            wResult.Result = new ArrayList<>();
            // 排序
            wStationList.sort(Comparator.comparing(LFSWorkAreaStation::getOrderNum));
            // 查询月计划
            Map<Integer, List<APSTaskPart>> wAPSTaskPartMap = wAPSTaskPartList.stream()
                    .collect(Collectors.groupingBy(APSTaskPart::getOrderID));
            Map<Integer, APSTaskPart> wTaskMap;
            Map<String, Object> wMap;
            Calendar wBaseTime = Calendar.getInstance();
            wBaseTime.set(2000, 1, 1);
            for (OMSOrder wOMSOrder : wOrderList) {
                wMap = CloneTool.Clone(wOMSOrder, Map.class);
                if (wAPSTaskPartMap.containsKey(wOMSOrder.ID)) {
                    wTaskMap = wAPSTaskPartMap.get(wOMSOrder.ID).stream()
                            .collect(Collectors.toMap(p -> p.PartID, p -> p, (k1, k2) -> k1));
                } else {
                    wTaskMap = new HashMap<>();
                }

                for (LFSWorkAreaStation wStation : wStationList) {

                    if (!wTaskMap.containsKey(wStation.StationID)) {
                        wMap.put("Station_" + wStation.StationID, wBaseTime);
                        wMap.put("Status_" + wStation.StationID, APSTaskStatus.Default.getValue());
                        continue;
                    }

                    APSTaskPart apsTaskPart = wTaskMap.get(wStation.StationID);

                    if (apsTaskPart.Status == 5) {
                        wMap.put("Status_" + wStation.StationID, 5);
                    } else if (wAPSTaskStepReleaseBPMList.stream().anyMatch(p -> p.OrderID == wOMSOrder.ID
                            && p.PartID == wStation.StationID && p.Status == 20)
                            || wLetGoNCRTaskList.stream()
                            .anyMatch(p -> p.OrderID == wOMSOrder.ID && p.StationID == wStation.StationID)) {
                        wMap.put("Status_" + wStation.StationID, 7);
                    } else {
                        SimpleDateFormat wSDF = new SimpleDateFormat("yyyyMMdd");
                        int wRShiftID = Integer.parseInt(wSDF.format(Calendar.getInstance().getTime()));
                        Calendar wCloneEndTime = (Calendar) apsTaskPart.EndTime.clone();
                        wCloneEndTime.add(Calendar.HOUR_OF_DAY, -12);

                        int wPShiftID = Integer.parseInt(wSDF.format(wCloneEndTime.getTime()));

                        if (apsTaskPart.Status == 2) {
                            wMap.put("Status_" + wStation.StationID, 2);
                        } else {
                            if (wRShiftID > wPShiftID) {
                                wMap.put("Status_" + wStation.StationID, 6);
                            } else {
                                wMap.put("Status_" + wStation.StationID, apsTaskPart.getStatus());
                            }
                        }
                    }

                    // 赋值tip
                    if (wAPSTaskStepReleaseBPMList.stream().anyMatch(p -> p.OrderID == wOMSOrder.ID
                            && p.PartID == wStation.StationID && p.Status == 20)) {
                        wMap.put("Tip_" + wStation.StationID,
                                wAPSTaskStepReleaseBPMList.stream().filter(p -> p.OrderID == wOMSOrder.ID
                                                && p.PartID == wStation.StationID && p.Status == 20)
                                        .collect(Collectors.toList()));
                    } else {
                        wMap.put("Tip_" + wStation.StationID, new ArrayList<APSTaskStepReleaseBPM>());
                    }

                    // 赋值NCR
                    if (wLetGoNCRTaskList.stream().anyMatch(p -> p.OrderID == wOMSOrder.ID
                            && p.StationID == wStation.StationID)) {
                        wMap.put("NCR_" + wStation.StationID,
                                wLetGoNCRTaskList.stream().filter(p -> p.OrderID == wOMSOrder.ID
                                        && p.StationID == wStation.StationID).collect(Collectors.toList()));
                    } else {
                        wMap.put("NCR_" + wStation.StationID, new ArrayList<APSTaskStepReleaseBPM>());
                    }

                    if (apsTaskPart.getStatus() == APSTaskStatus.Done.getValue()) {
                        wMap.put("Station_" + wStation.StationID, apsTaskPart.FinishWorkTime);
                        continue;
                    }

                    wMap.put("Station_" + wStation.StationID, apsTaskPart.EndTime);
                }
                wResult.Result.add(wMap);
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<Map<String, Object>>> ChangeToTableByEndTimeAndTip(List<OMSOrder> wOrderList,
                                                                                 List<APSTaskPart> wAPSTaskPartList,
                                                                                 List<LFSWorkAreaStation> wStationList,
                                                                                 List<APSTaskStepReleaseBPM> wAPSTaskStepReleaseBPMList,
                                                                                 List<NCRTask> wLetGoNCRTaskList) {
        ServiceResult<List<Map<String, Object>>> wResult = new ServiceResult<>();
        try {
            wResult.Result = new ArrayList<>();

            wStationList.sort(Comparator.comparing(LFSWorkAreaStation::getOrderNum));

            Map<Integer, List<APSTaskPart>> wAPSTaskPartMap = wAPSTaskPartList
                    .stream().collect(Collectors.groupingBy(APSTaskPart::getOrderID));
            Map<Integer, APSTaskPart> wTaskMap;
            Map<String, Object> wMap;
            Calendar wBaseTime = Calendar.getInstance();
            wBaseTime.set(2000, 1, 1);
            for (OMSOrder wOMSOrder : wOrderList) {
                wMap = CloneTool.Clone(wOMSOrder, Map.class);
                if (wAPSTaskPartMap.containsKey(wOMSOrder.ID)) {
                    wTaskMap = (wAPSTaskPartMap.get(wOMSOrder.ID)).stream()
                            .collect(Collectors.toMap(p -> p.PartID, p -> p, (k1, k2) -> k1));
                } else {
                    wTaskMap = new HashMap<>();
                }

                for (LFSWorkAreaStation wStation : wStationList) {

                    if (wTaskMap.containsKey(wStation.StationID)) {
                        APSTaskPart wTaskPart = wTaskMap.get(wStation.StationID);
                        if (wTaskPart.Status == 5) {
                            wMap.put("Station_" + wStation.StationID, wTaskPart.FinishWorkTime);
                        } else {
                            wMap.put("Station_" + wStation.StationID, wTaskPart.EndTime);
                        }
                    } else {
                        wMap.put("Station_" + wStation.StationID, wBaseTime);
                    }

                    // 赋值状态
                    if (wTaskMap.containsKey(wStation.StationID)) {
                        APSTaskPart apsTaskPart = wTaskMap.get(wStation.StationID);

                        if (apsTaskPart.Status == 5) {
                            wMap.put("Status_" + wStation.StationID, 5);
                        } else if (wAPSTaskStepReleaseBPMList.stream()
                                .anyMatch(p -> p.StepIDs.contains(String.valueOf(wStation.StationID)))
                                || wLetGoNCRTaskList.stream().anyMatch(p -> p.ProcessID == wStation.StationID)) {
                            wMap.put("Status_" + wStation.StationID, 7);
                        } else {
                            SimpleDateFormat wSDF = new SimpleDateFormat("yyyyMMdd");
                            int wRShiftID = Integer.parseInt(wSDF.format(Calendar.getInstance().getTime()));

                            Calendar wTime = (Calendar) apsTaskPart.EndTime.clone();
                            wTime.add(Calendar.HOUR_OF_DAY, -12);

                            int wPShiftID = Integer.parseInt(wSDF.format(wTime.getTime()));

                            if (apsTaskPart.Status == 2) {
                                wMap.put("Status_" + wStation.StationID, 2);
                            } else {
                                if (wRShiftID > wPShiftID) {
                                    wMap.put("Status_" + wStation.StationID, 6);
                                } else {
                                    wMap.put("Status_" + wStation.StationID, apsTaskPart.getStatus());
                                }

                            }
                        }
                    } else {
                        wMap.put("Status_" + wStation.StationID, 0);
                    }

                    // 赋值tip
                    if (wAPSTaskStepReleaseBPMList.stream()
                            .anyMatch(p -> p.StepIDs.contains(String.valueOf(wStation.StationID)))) {
                        wMap.put("Tip_" + wStation.StationID,
                                wAPSTaskStepReleaseBPMList.stream()
                                        .filter(p -> p.StepIDs.contains(String.valueOf(wStation.StationID)))
                                        .collect(Collectors.toList()));
                    } else {
                        wMap.put("Tip_" + wStation.StationID, new ArrayList<APSTaskStepReleaseBPM>());
                    }

                    // 赋值NCR
                    if (wLetGoNCRTaskList.stream().anyMatch(p -> p.ProcessID == wStation.StationID)) {
                        wMap.put("NCR_" + wStation.StationID,
                                wLetGoNCRTaskList.stream().filter(p -> p.ProcessID == wStation.StationID)
                                        .collect(Collectors.toList()));
                    } else {
                        wMap.put("NCR_" + wStation.StationID, new ArrayList<NCRTask>());
                    }
                }
                wResult.Result.add(wMap);
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<BMSEmployee>> APS_QueryAuditorAndSchedulerByPartID(BMSEmployee wLoginUser, int wPartID) {
        ServiceResult<List<BMSEmployee>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            List<LFSWorkAreaStation> wLFSWorkAreaStationList = LFSServiceImpl.getInstance()
                    .LFS_QueryWorkAreaStationList(wLoginUser).List(LFSWorkAreaStation.class);
            if (wLFSWorkAreaStationList == null || wLFSWorkAreaStationList.size() <= 0)
                return wResult;
            wLFSWorkAreaStationList = wLFSWorkAreaStationList.stream()
                    .filter(p -> p.StationID == wPartID && p.Active == 1).collect(Collectors.toList());
            if (wLFSWorkAreaStationList.size() <= 0)
                return wResult;

            LFSWorkAreaStation wLFSWorkAreaStation = wLFSWorkAreaStationList.get(0);
            if (wLFSWorkAreaStation.WorkAreaID <= 0)
                return wResult;

            List<LFSWorkAreaChecker> wLFSWorkAreaCheckerList = LFSServiceImpl.getInstance()
                    .LFS_QueryWorkAreaCheckerList(wLoginUser).List(LFSWorkAreaChecker.class);
            if (wLFSWorkAreaCheckerList == null || wLFSWorkAreaCheckerList.size() <= 0)
                return wResult;
            wLFSWorkAreaCheckerList = wLFSWorkAreaCheckerList.stream()
                    .filter(p -> p.WorkAreaID == wLFSWorkAreaStation.WorkAreaID && p.Active == 1)
                    .collect(Collectors.toList());
            if (wLFSWorkAreaCheckerList.size() <= 0)
                return wResult;

            LFSWorkAreaChecker wLFSWorkAreaChecker = wLFSWorkAreaCheckerList.get(0);
            for (int wUserID : wLFSWorkAreaChecker.LeaderIDList) {
                if (wResult.Result.stream().anyMatch(p -> p.ID == wUserID))
                    continue;

                BMSEmployee wBMSEmployee = APSConstans.GetBMSEmployee(wUserID);
                if (wBMSEmployee != null && wBMSEmployee.ID > 0) {
                    wResult.Result.add(wBMSEmployee);
                }
            }
            for (int wUserID : wLFSWorkAreaChecker.ScheduleIDList) {
                if (wResult.Result.stream().anyMatch(p -> p.ID == wUserID))
                    continue;

                BMSEmployee wBMSEmployee = APSConstans.GetBMSEmployee(wUserID);
                if (wBMSEmployee != null && wBMSEmployee.ID > 0) {
                    wResult.Result.add(wBMSEmployee);
                }
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<APSPartPointWeekPlan> APS_QueryPartPointWeekPlan(BMSEmployee wLoginUser, int wID) {
        ServiceResult<APSPartPointWeekPlan> wResult = new ServiceResult<>();
        wResult.Result = new APSPartPointWeekPlan();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wResult.Result = APSPartPointWeekPlanDAO.getInstance().SelectByID(wLoginUser, wID, wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<APSPartPointWeekPlan>> APS_QueryPartPointWeekPlanList(BMSEmployee wLoginUser,
                                                                                    int wOrderID, int wPartID,
                                                                                    int wPartPointID) {
        ServiceResult<List<APSPartPointWeekPlan>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wResult.Result = APSPartPointWeekPlanDAO.getInstance().SelectList(wLoginUser, -1, wOrderID, wPartID,
                    wPartPointID, wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> APS_UpdatePartPointWeekPlan(BMSEmployee wLoginUser,
                                                              APSPartPointWeekPlan wAPSPartPointWeekPlan) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            if (wAPSPartPointWeekPlan.ID <= 0) {
                wAPSPartPointWeekPlan.CreateID = wLoginUser.ID;
                wAPSPartPointWeekPlan.CreateTime = Calendar.getInstance();
            }
            wResult.Result = APSPartPointWeekPlanDAO.getInstance().Update(wLoginUser, wAPSPartPointWeekPlan,
                    wErrorCode);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> APS_SavePartPointWeekPlanList(BMSEmployee wLoginUser,
                                                                List<APSPartPointWeekPlan> wAPSPartPointWeekPlanList) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            // 删除此订单、此工位的保存数据
            List<APSPartPointWeekPlan> wDeleteList = APSPartPointWeekPlanDAO.getInstance().SelectList(wLoginUser, -1,
                    wAPSPartPointWeekPlanList.get(0).OrderID, wAPSPartPointWeekPlanList.get(0).PartID, -1,
                    wErrorCode);
            if (wDeleteList != null && wDeleteList.size() > 0) {
                APSPartPointWeekPlanDAO.getInstance().DeleteList(wLoginUser, wDeleteList, wErrorCode);
            }
            // 循环批量保存
            for (APSPartPointWeekPlan wAPSPartPointWeekPlan : wAPSPartPointWeekPlanList) {
                wAPSPartPointWeekPlan.CreateID = wLoginUser.ID;
                wAPSPartPointWeekPlan.CreateTime = Calendar.getInstance();
                APSPartPointWeekPlanDAO.getInstance().Update(wLoginUser, wAPSPartPointWeekPlan, wErrorCode);
            }

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<FPCRoutePartPoint>> APS_QueryBopPartPointList(BMSEmployee wLoginUser, int wOrderID,
                                                                            int wPartID) {
        ServiceResult<List<FPCRoutePartPoint>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            OMSOrder wOMSOrder = OMSOrderDAO.getInstance().SelectByID(wLoginUser, wOrderID, wErrorCode);
            if (wOMSOrder == null || wOMSOrder.RouteID <= 0) {
                wResult.FaultCode += "提示：该项目未设置工艺BOP!";
                return wResult;
            }

            wResult.Result = FMCServiceImpl.getInstance().FPC_QueryRoutePartPointListByRouteID(wLoginUser,
                    wOMSOrder.RouteID, wPartID).List(FPCRoutePartPoint.class);

            List<APSPartPointWeekPlan> apsPartPointWeekPlans = APSPartPointWeekPlanDAO.getInstance()
                    .SelectList(wLoginUser, -1, wOrderID, wPartID, -1, wErrorCode);
            wResult.CustomResult.put("SaveList", apsPartPointWeekPlans);

            wResult.setFaultCode(MESException.getEnumType(wErrorCode.Result).getLable());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            logger.error(e.toString());
        }
        return wResult;
    }
}
